Skip to content
This repository was archived by the owner on Mar 23, 2023. It is now read-only.

Commit 172f96e

Browse files
jacobheundaviddias
authored andcommitted
docs: add s3 lock to the example
License: MIT Signed-off-by: Jacob Heun <[email protected]>
1 parent 2fcea97 commit 172f96e

File tree

3 files changed

+145
-28
lines changed

3 files changed

+145
-28
lines changed

examples/full-s3-repo/index.js

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ const IPFS = require('ipfs')
55
const Repo = require('ipfs-repo')
66
const S3 = require('aws-sdk').S3
77
const S3Store = require('../../src')
8+
const S3Lock = require('./s3-lock')
89

9-
let fileMultihash
10+
// Initialize the AWS S3 instance
1011
const s3 = new S3({
1112
params: {
1213
Bucket: 'my-bucket'
@@ -15,6 +16,11 @@ const s3 = new S3({
1516
secretAccessKey: 'mysecretkey'
1617
})
1718

19+
// Create our custom lock
20+
const s3Store = new S3Store('/tmp/test/.ipfs', { s3 })
21+
const s3Lock = new S3Lock(s3Store)
22+
23+
// Create the IPFS Repo, full backed by S3
1824
const repo = new Repo('/tmp/test/.ipfs', {
1925
storageBackends: {
2026
root: S3Store,
@@ -28,34 +34,46 @@ const repo = new Repo('/tmp/test/.ipfs', {
2834
keys: { s3 },
2935
datastore: { s3 }
3036
},
31-
lock: 'memory'
37+
lock: s3Lock
3238
})
3339

40+
// Create a new IPFS node with our S3 backed Repo
3441
let node = new IPFS({
35-
repo: repo
42+
repo
3643
})
3744

38-
series([
39-
(cb) => node.on('ready', cb),
40-
(cb) => node.version((err, version) => {
41-
if (err) { return cb(err) }
42-
console.log('Version:', version.version)
43-
cb()
44-
}),
45-
(cb) => node.files.add({
46-
path: 'hello.txt',
47-
content: Buffer.from('Hello World 101')
48-
}, (err, filesAdded) => {
49-
if (err) { return cb(err) }
50-
51-
console.log('\nAdded file:', filesAdded[0].path, filesAdded[0].hash)
52-
fileMultihash = filesAdded[0].hash
53-
cb()
54-
}),
55-
(cb) => node.files.cat(fileMultihash, (err, data) => {
56-
if (err) { return cb(err) }
57-
58-
console.log('\nFile content:')
59-
process.stdout.write(data)
60-
})
61-
])
45+
// Test out the repo by sending and fetching some data
46+
node.on('ready', () => {
47+
console.log('Ready')
48+
node.version()
49+
.then((version) => {
50+
console.log('Version:', version.version)
51+
})
52+
// Once we have the version, let's add a file to IPFS
53+
.then(() => {
54+
return node.files.add({
55+
path: 'hello.txt',
56+
content: Buffer.from('Hello World 101')
57+
})
58+
})
59+
// Log out the added files metadata and cat the file from IPFS
60+
.then((filesAdded) => {
61+
console.log('\nAdded file:', filesAdded[0].path, filesAdded[0].hash)
62+
return node.files.cat(filesAdded[0].hash)
63+
})
64+
// Print out the files contents to console
65+
.then((data) => {
66+
console.log('\nFetched file content:')
67+
process.stdout.write(data)
68+
})
69+
// Log out the error, if there is one
70+
.catch((err) => {
71+
console.log('File Processing Error:', err)
72+
})
73+
// After everything is done, shut the node down
74+
// We don't need to worry about catching errors here
75+
.then(() => {
76+
console.log('\n\nStopping the node')
77+
return node.stop()
78+
})
79+
})

examples/full-s3-repo/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@
1313
"async": "^2.6.0",
1414
"aws-sdk": "^2.220.1",
1515
"ipfs": "^0.28.2",
16-
"ipfs-repo": "^0.18.7"
16+
"ipfs-repo": "^0.20.0"
1717
}
1818
}

examples/full-s3-repo/s3-lock.js

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(dir), (err, data) => {
88+
if (err && err.message.match(/not found/)) {
89+
return callback(null, false)
90+
} else if (err) {
91+
return callback(err)
92+
}
93+
94+
callback(null, true)
95+
})
96+
}
97+
}
98+
99+
module.exports = S3Lock

0 commit comments

Comments
 (0)