Skip to content
This repository was archived by the owner on Feb 12, 2024. It is now read-only.

Commit 1c23edc

Browse files
committed
docs: update custom repo example
remove ability to add repoOptions in favor of just supplying a repo chore: remove outdated options
1 parent f50cd59 commit 1c23edc

File tree

8 files changed

+177
-133
lines changed

8 files changed

+177
-133
lines changed

examples/custom-ipfs-repo/README.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
# Customizing the IPFS Repo
22

3-
> This example shows you how to customize your repository, including where your data is stored and how the repo locking is managed.
3+
This example shows you how to customize your repository, including where your data is stored and how the repo locking is managed. Customizing your repo makes it easier to extend IPFS for your particular needs. You may want to customize your repo if:
4+
5+
* If you want to store data somewhere that’s not on your local disk, like S3, a Redis instance, a different machine on your local network, or in your own database system, like MongoDB or Postgres, you might use a custom datastore.
6+
* If you have multiple browser windows or workers sharing the same IPFS storage, you might want to use a custom lock to coordinate between them. (Locking is currently only used to ensure a single IPFS instance can access a repo at a time. This check is done on `repo.open()`. A more complex lock, coupled with a custom datastore, could allow for safe writes to a single datastore from multiple IPFS nodes.)
7+
8+
9+
You can find full details on customization in the [IPFS Repo Docs](https://github.com/ipfs/js-ipfs-repo#setup).
410

511
## Run this example
612

@@ -12,13 +18,13 @@
1218
## Other Options
1319

1420
### Custom Repo Lock
15-
> This example sets the repo locker to `false`, preventing any locking from happening. If you would like to control how locking happens, such as with a centralized S3 ipfs repo, you can pass in your own custom locker. See [custom-locker.js](./custom-locker.js) for an example of a custom locker that can be used for [datastore-s3](https://github.com/ipfs/js-datastore-s3).
21+
This example sets the repo locker to `false`, preventing any locking from happening. If you would like to control how locking happens, such as with a centralized S3 IPFS Repo, you can pass in your own custom lock. See [custom-lock.js](./custom-lock.js) for an example of a custom lock that can be used for [datastore-s3](https://github.com/ipfs/js-datastore-s3).
1622

1723
```js
18-
const S3Locker = require('./custom-locker')
24+
const S3Lock = require('./custom-lock')
1925

2026
const repo = new Repo('/tmp/.ipfs', {
2127
...
22-
locker: new S3Locker(s3DatastoreInstance)
28+
lock: new S3Lock(s3DatastoreInstance)
2329
})
2430
```
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
'use strict'
2+
3+
const PATH = require('path')
4+
5+
/**
6+
* Uses an object in an S3 bucket as a lock to signal that an IPFS repo is in use.
7+
* When the object exists, the repo is in use. You would normally use this to make
8+
* sure multiple IPFS nodes don’t use the same S3 bucket as a datastore at the same time.
9+
*/
10+
class S3Lock {
11+
constructor (s3Datastore) {
12+
this.s3 = s3Datastore
13+
}
14+
15+
/**
16+
* Returns the location of the lock file given the path it should be located at
17+
*
18+
* @private
19+
* @param {string} dir
20+
* @returns {string}
21+
*/
22+
getLockfilePath (dir) {
23+
return PATH.join(dir, 'repo.lock')
24+
}
25+
26+
/**
27+
* Creates the lock. This can be overriden to customize where the lock should be created
28+
*
29+
* @param {string} dir
30+
* @param {function(Error, LockCloser)} callback
31+
* @returns {void}
32+
*/
33+
lock (dir, callback) {
34+
const lockPath = this.getLockfilePath(dir)
35+
36+
this.locked(dir, (err, alreadyLocked) => {
37+
if (err || alreadyLocked) {
38+
return callback(new Error('The repo is already locked'))
39+
}
40+
41+
// There's no lock yet, create one
42+
this.s3.put(lockPath, Buffer.from(''), (err, data) => {
43+
if (err) {
44+
return callback(err, null)
45+
}
46+
47+
callback(null, this.getCloser(lockPath))
48+
})
49+
})
50+
}
51+
52+
/**
53+
* Returns a LockCloser, which has a `close` method for removing the lock located at `lockPath`
54+
*
55+
* @param {string} lockPath
56+
* @returns {LockCloser}
57+
*/
58+
getCloser (lockPath) {
59+
return {
60+
/**
61+
* Removes the lock. This can be overriden to customize how the lock is removed. This
62+
* is important for removing any created locks.
63+
*
64+
* @param {function(Error)} callback
65+
* @returns {void}
66+
*/
67+
close: (callback) => {
68+
this.s3.delete(lockPath, (err) => {
69+
if (err && err.statusCode !== 404) {
70+
return callback(err)
71+
}
72+
73+
callback(null)
74+
})
75+
}
76+
}
77+
}
78+
79+
/**
80+
* Calls back on whether or not a lock exists. Override this method to customize how the check is made.
81+
*
82+
* @param {string} dir
83+
* @param {function(Error, boolean)} callback
84+
* @returns {void}
85+
*/
86+
locked (dir, callback) {
87+
this.s3.get(this.getLockfilePath(), (err, data) => {
88+
if (err && err.message.match(/not found/)) {
89+
return callback(err, false)
90+
} else if (err) {
91+
return callback(err)
92+
}
93+
94+
callback(null, true)
95+
})
96+
}
97+
}
98+
99+
module.exports = S3Lock

examples/custom-ipfs-repo/custom-locker.js

Lines changed: 0 additions & 77 deletions
This file was deleted.

examples/custom-ipfs-repo/index.js

Lines changed: 61 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
'use strict'
22

3-
const series = require('async/series')
43
const IPFS = require('ipfs')
4+
const Repo = require('ipfs-repo')
5+
const fsLock = require('ipfs-repo/src/lock')
56

67
// Create our custom options
78
const customRepositoryOptions = {
89

910
/**
10-
* Storage Backends are fully customizable. Each backend can be stored in seperate services,
11-
* or in a single service. Options can be passed into the datastores via the storageBackendOptions
12-
* property shown below.
11+
* IPFS nodes store different information in separate storageBackends, or datastores.
12+
* Each storage backend can use the same type of datastore or a different one — you
13+
* could store your keys in a levelDB database while everything else is in files,
14+
* for example. (See https://github.com/ipfs/interface-datastore for more about datastores.)
1315
*/
1416
storageBackends: {
1517
root: require('datastore-fs'), // version and config data will be saved here
@@ -20,58 +22,72 @@ const customRepositoryOptions = {
2022

2123
/**
2224
* Storage Backend Options will get passed into the instantiation of their counterpart
23-
* in Storage Backends. If you create a custom datastore, this is where you can pass in
24-
* custom insantiation. You can see an S3 datastore example at:
25+
* in `storageBackends`. If you create a custom datastore, this is where you can pass in
26+
* custom constructor arguments. You can see an S3 datastore example at:
2527
* https://github.com/ipfs/js-datastore-s3/tree/master/examples/full-s3-repo
2628
*/
2729
storageBackendOptions: {
30+
root: {
31+
extension: '.ipfsroot', // Used by datastore-fs; Appended to all files
32+
errorIfExists: false, // Used by datastore-fs; If the datastore exists, don't throw an error
33+
createIfMissing: true // Used by datastore-fs; If the datastore doesn't exist yet, create it
34+
},
2835
blocks: {
29-
sharding: true,
30-
extension: '.data'
36+
sharding: false, // Used by IPFSRepo Blockstore to determine sharding; Ignored by datastore-fs
37+
extension: '.ipfsblock',
38+
errorIfExists: false,
39+
createIfMissing: true
40+
},
41+
keys: {
42+
extension: '.ipfskey',
43+
errorIfExists: false,
44+
createIfMissing: true
45+
},
46+
datastore: {
47+
extension: '.ipfsds',
48+
errorIfExists: false,
49+
createIfMissing: true
3150
}
3251
},
3352

34-
// false will disable locking, you can also pass in a custom locker
35-
locker: false
53+
/**
54+
* A custom lock can be added here. Or the build in Repo `fs` or `memory` locks can be used.
55+
* See https://github.com/ipfs/js-ipfs-repo for more details on setting the lock.
56+
*/
57+
lock: fsLock
3658
}
3759

3860
// Initialize our IPFS node with the custom repo options
3961
const node = new IPFS({
40-
repo: '/tmp/custom-repo/.ipfs',
41-
repoOptions: customRepositoryOptions
62+
repo: new Repo('/tmp/custom-repo/.ipfs', customRepositoryOptions)
4263
})
4364

4465
// Test the new repo by adding and fetching some data
45-
let fileMultihash
46-
series([
47-
(cb) => node.on('ready', cb),
48-
(cb) => node.version((err, version) => {
49-
if (err) {
50-
return cb(err)
51-
}
52-
53-
console.log('Version:', version.version)
54-
cb()
55-
}),
56-
(cb) => node.files.add({
57-
path: 'test-data.txt',
58-
content: Buffer.from('We are using a customized repo!')
59-
}, (err, filesAdded) => {
60-
if (err) {
61-
return cb(err)
62-
}
63-
64-
console.log('\nAdded file:', filesAdded[0].path, filesAdded[0].hash)
65-
fileMultihash = filesAdded[0].hash
66-
cb()
67-
}),
68-
(cb) => node.files.cat(fileMultihash, (err, data) => {
69-
if (err) {
70-
return cb(err)
71-
}
72-
73-
console.log('\nFetched file content:')
74-
process.stdout.write(data)
75-
cb()
76-
})
77-
])
66+
node.on('ready', () => {
67+
console.log('Ready')
68+
node.version()
69+
.then((version) => {
70+
console.log('Version:', version.version)
71+
})
72+
// Once we have the version, let's add a file to IPFS
73+
.then(() => {
74+
return node.files.add({
75+
path: 'test-data.txt',
76+
content: Buffer.from('We are using a customized repo!')
77+
})
78+
})
79+
// Log out the added files metadata and cat the file from IPFS
80+
.then((filesAdded) => {
81+
console.log('\nAdded file:', filesAdded[0].path, filesAdded[0].hash)
82+
return node.files.cat(filesAdded[0].hash)
83+
})
84+
// Print out the files contents to console
85+
.then((data) => {
86+
console.log('\nFetched file content:')
87+
process.stdout.write(data)
88+
})
89+
// Log out the error, if there is one
90+
.catch((err) => {
91+
console.log('File Processing Error:', err)
92+
})
93+
})

examples/custom-ipfs-repo/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
},
1010
"license": "MIT",
1111
"dependencies": {
12-
"async": "^2.6.0",
1312
"datastore-fs": "~0.4.2",
14-
"ipfs": "file:../../"
13+
"ipfs": "file:../../",
14+
"ipfs-repo": "~0.19.0"
1515
}
1616
}

src/core/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class IPFS extends EventEmitter {
4343

4444
if (typeof options.repo === 'string' ||
4545
options.repo === undefined) {
46-
this._repo = defaultRepo(options.repo, options.repoPath)
46+
this._repo = defaultRepo(options.repo)
4747
} else {
4848
this._repo = options.repo
4949
}

src/core/runtime/repo-browser.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
const IPFSRepo = require('ipfs-repo')
44

5-
module.exports = (dir, options) => {
5+
module.exports = (dir) => {
66
const repoPath = dir || 'ipfs'
7-
return new IPFSRepo(repoPath, options)
7+
return new IPFSRepo(repoPath)
88
}

src/core/runtime/repo-nodejs.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ const os = require('os')
44
const IPFSRepo = require('ipfs-repo')
55
const path = require('path')
66

7-
module.exports = (dir, options) => {
7+
module.exports = (dir) => {
88
const repoPath = dir || path.join(os.homedir(), '.jsipfs')
99

10-
return new IPFSRepo(repoPath, options)
10+
return new IPFSRepo(repoPath)
1111
}

0 commit comments

Comments
 (0)