Skip to content

Commit 0e2d91f

Browse files
achingbrainjacobheun
authored andcommittedJul 12, 2019
feat: refactor to use async/await (#7)
BREAKING CHANGE: API refactored to use async/await
1 parent eccffe5 commit 0e2d91f

File tree

4 files changed

+113
-177
lines changed

4 files changed

+113
-177
lines changed
 

‎.aegir.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ const server = createServer()
66

77
module.exports = {
88
hooks: {
9-
pre: server.start.bind(server),
10-
post: server.stop.bind(server)
9+
browser: {
10+
pre: () => server.start(),
11+
post: () => server.stop()
12+
}
1113
}
1214
}

‎package.json

+6-7
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,16 @@
1919
},
2020
"devDependencies": {
2121
"aegir": "^19.0.5",
22+
"async-iterator-all": "^1.0.0",
2223
"chai": "^4.2.0",
2324
"cids": "^0.7.1",
24-
"go-ipfs-dep": "^0.4.21",
25-
"ipfsd-ctl": "^0.43.0"
25+
"go-ipfs-dep": "~0.4.17",
26+
"ipfsd-ctl": "~0.44.1",
27+
"peer-id": "~0.13.1"
2628
},
2729
"dependencies": {
28-
"async": "^2.6.2",
29-
"ipfs-http-client": "^33.0.2",
30-
"multiaddr": "^6.1.0",
31-
"peer-id": "^0.12.2",
32-
"peer-info": "^0.15.1"
30+
"ipfs-http-client": "^33.1.0",
31+
"multiaddr": "^6.1.0"
3332
},
3433
"contributors": [
3534
"Alan Shaw <alan.shaw@protocol.ai>",

‎src/index.js

+25-39
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@ const dht = require('ipfs-http-client/src/dht')
44
const swarm = require('ipfs-http-client/src/swarm')
55
const refs = require('ipfs-http-client/src/files-regular/refs')
66
const defaultConfig = require('ipfs-http-client/src/utils/default-config')
7-
const series = require('async/series')
8-
const parallel = require('async/parallel')
9-
const reflect = require('async/reflect')
107
const multiaddr = require('multiaddr')
118

129
const DEFAULT_MAX_TIMEOUT = 30e3 // 30 second default
@@ -60,26 +57,18 @@ class DelegatedContentRouting {
6057
* @param {CID} key
6158
* @param {object} options
6259
* @param {number} options.maxTimeout How long the query can take. Defaults to 30 seconds
63-
* @param {function(Error, Array<PeerInfo>)} callback
64-
* @returns {void}
60+
* @returns {AsyncIterable<PeerInfo>}
6561
*/
66-
findProviders (key, options, callback) {
67-
if (typeof options === 'function') {
68-
callback = options
69-
options = {}
70-
} else if (typeof options === 'number') { // This will be deprecated in a next release
71-
options = {
72-
maxTimeout: options
73-
}
74-
} else {
75-
options = options || {}
76-
}
77-
62+
async * findProviders (key, options = {}) {
7863
options.maxTimeout = options.maxTimeout || DEFAULT_MAX_TIMEOUT
7964

80-
this.dht.findProvs(key.toString(), {
65+
const results = await this.dht.findProvs(key, {
8166
timeout: `${options.maxTimeout}ms` // The api requires specification of the time unit (s/ms)
82-
}, callback)
67+
})
68+
69+
for (let i = 0; i < results.length; i++) {
70+
yield results[i]
71+
}
8372
}
8473

8574
/**
@@ -91,32 +80,29 @@ class DelegatedContentRouting {
9180
*
9281
* @param {CID} key
9382
* @param {function(Error)} callback
94-
* @returns {void}
83+
* @returns {Promise<void>}
9584
*/
96-
provide (key, callback) {
85+
async provide (key) {
9786
const addrs = this.bootstrappers.map((addr) => {
9887
return addr.encapsulate(`/p2p-circuit/ipfs/${this.peerId.toB58String()}`)
9988
})
10089

101-
series([
102-
(cb) => parallel(addrs.map((addr) => {
103-
return reflect((cb) => this.swarm.connect(addr.toString(), cb))
104-
}), (err, results) => {
105-
if (err) {
106-
return cb(err)
107-
}
90+
const results = await Promise.all(
91+
addrs.map((addr) => {
92+
return this.swarm.connect(addr.toString()).catch(() => {})
93+
})
94+
)
10895

109-
// only some need to succeed
110-
const success = results.filter((res) => res.error == null)
111-
if (success.length === 0) {
112-
return cb(new Error('unable to swarm.connect using p2p-circuit'))
113-
}
114-
cb()
115-
}),
116-
(cb) => {
117-
this.refs(key.toString(), { recursive: true }, cb)
118-
}
119-
], (err) => callback(err))
96+
// only some need to succeed
97+
const success = results.filter((res) => res && res.error == null)
98+
99+
if (success.length === 0) {
100+
throw new Error('unable to swarm.connect using p2p-circuit')
101+
}
102+
103+
this.refs(key.toBaseEncodedString(), {
104+
recursive: true
105+
})
120106
}
121107
}
122108

‎test/index.spec.js

+78-129
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,17 @@
33

44
const expect = require('chai').expect
55
const IPFSFactory = require('ipfsd-ctl')
6-
const parallel = require('async/parallel')
7-
const waterfall = require('async/waterfall')
86
const CID = require('cids')
97
const PeerId = require('peer-id')
10-
11-
const factory = IPFSFactory.create({ type: 'go' })
8+
const all = require('async-iterator-all')
9+
const factory = IPFSFactory.create({
10+
type: 'go'
11+
})
1212

1313
const DelegatedContentRouting = require('../src')
1414

15-
function spawnNode (bootstrap, callback) {
16-
if (typeof bootstrap === 'function') {
17-
callback = bootstrap
18-
bootstrap = []
19-
}
20-
21-
factory.spawn({
15+
async function spawnNode (bootstrap = []) {
16+
const node = await factory.spawn({
2217
// Lock down the nodes so testing can be deterministic
2318
config: {
2419
Bootstrap: bootstrap,
@@ -28,59 +23,47 @@ function spawnNode (bootstrap, callback) {
2823
}
2924
}
3025
}
31-
}, (err, node) => {
32-
if (err) return callback(err)
26+
})
3327

34-
node.api.id((err, id) => {
35-
if (err) return callback(err)
28+
const id = await node.api.id()
3629

37-
callback(null, node, id)
38-
})
39-
})
30+
return {
31+
node,
32+
id
33+
}
4034
}
4135

4236
describe('DelegatedContentRouting', function () {
4337
this.timeout(20 * 1000) // we're spawning daemons, give ci some time
4438

4539
let selfNode
4640
let selfId
47-
let delegatedNode
48-
let delegatedId
41+
let delegateNode
4942
let bootstrapNode
5043
let bootstrapId
5144

52-
before((done) => {
53-
waterfall([
54-
// Spawn a "bootstrap" node that doesnt connect to anything
55-
(cb) => spawnNode(cb),
56-
(ipfsd, id, cb) => {
57-
bootstrapNode = ipfsd
58-
bootstrapId = id
59-
cb()
60-
},
61-
// Spawn our local node and bootstrap the bootstrapper node
62-
(cb) => spawnNode(bootstrapId.addresses, cb),
63-
(ipfsd, id, cb) => {
64-
selfNode = ipfsd
65-
selfId = PeerId.createFromB58String(id.id)
66-
cb()
67-
},
68-
// Spawn the delegate node and bootstrap the bootstrapper node
69-
(cb) => spawnNode(bootstrapId.addresses, cb),
70-
(ipfsd, id, cb) => {
71-
delegatedNode = ipfsd
72-
delegatedId = PeerId.createFromB58String(id.id)
73-
cb()
74-
}
75-
], done)
45+
before(async () => {
46+
// Spawn a "Boostrap" node that doesnt connect to anything
47+
const bootstrap = await spawnNode()
48+
bootstrapNode = bootstrap.node
49+
bootstrapId = bootstrap.id
50+
51+
// Spawn our local node and bootstrap the bootstrapper node
52+
const self = await spawnNode(bootstrapId.addresses)
53+
selfNode = self.node
54+
selfId = PeerId.createFromB58String(self.id.id)
55+
56+
// Spawn the delegate node and bootstrap the bootstrapper node
57+
const delegate = await spawnNode(bootstrapId.addresses)
58+
delegateNode = delegate.node
7659
})
7760

78-
after((done) => {
79-
parallel([
80-
(cb) => selfNode.stop(cb),
81-
(cb) => delegatedNode.stop(cb),
82-
(cb) => bootstrapNode.stop(cb)
83-
], done)
61+
after(() => {
62+
return Promise.all([
63+
selfNode.stop(),
64+
delegateNode.stop(),
65+
bootstrapNode.stop()
66+
])
8467
})
8568

8669
describe('create', () => {
@@ -127,96 +110,62 @@ describe('DelegatedContentRouting', function () {
127110

128111
describe('findProviders', () => {
129112
const cid = new CID('QmS4ustL54uo8FzR9455qaxZwuMiUhyvMcX9Ba8nUH4uVv')
130-
before('register providers', (done) => {
131-
parallel([
132-
(cb) => bootstrapNode.api.dht.provide(cid, cb),
133-
(cb) => selfNode.api.dht.provide(cid, cb)
134-
], done)
113+
114+
before('register providers', async () => {
115+
await bootstrapNode.api.dht.provide(cid)
116+
await selfNode.api.dht.provide(cid)
135117
})
136118

137-
it('should be able to find providers through the delegate node', function (done) {
138-
waterfall([
139-
(cb) => {
140-
const opts = delegatedNode.apiAddr.toOptions()
141-
const routing = new DelegatedContentRouting(selfId, {
142-
protocol: 'http',
143-
port: opts.port,
144-
host: opts.host
145-
})
146-
routing.findProviders(cid, cb)
147-
},
148-
(providers, cb) => {
149-
// We should get our local node and the bootstrap node as providers.
150-
// The delegate node is not included, because it is handling the requests
151-
expect(providers).to.have.length(2)
152-
expect(providers.map((p) => p.id.toB58String())).to.have.members([
153-
bootstrapId.id,
154-
selfId.toB58String()
155-
])
156-
cb()
157-
}
158-
], done)
119+
it('should be able to find providers through the delegate node', async () => {
120+
const opts = delegateNode.apiAddr.toOptions()
121+
const routing = new DelegatedContentRouting(selfId, {
122+
protocol: 'http',
123+
port: opts.port,
124+
host: opts.host
125+
})
126+
127+
const providers = await all(routing.findProviders(cid))
128+
129+
// We should get the bootstrap node as provider
130+
// The delegate node is not included, because it is handling the requests
131+
expect(providers.map((p) => p.id.toB58String())).to.include(bootstrapId.id, 'Did not include bootstrap node')
132+
expect(providers.map((p) => p.id.toB58String())).to.include(selfId.toB58String(), 'Did not include self node')
159133
})
160134

161-
it('should be able to specify a maxTimeout', function (done) {
162-
waterfall([
163-
(cb) => {
164-
const opts = delegatedNode.apiAddr.toOptions()
165-
const routing = new DelegatedContentRouting(selfId, {
166-
protocol: 'http',
167-
port: opts.port,
168-
host: opts.host
169-
})
170-
const cid = new CID('QmS4ustL54uo8FzR9455qaxZwuMiUhyvMcX9Ba8nUH4uVv')
171-
routing.findProviders(cid, { maxTimeout: 5e3 }, cb)
172-
},
173-
(providers, cb) => {
174-
// We should get our local node and the bootstrap node as providers.
175-
// The delegate node is not included, because it is handling the requests
176-
expect(providers).to.have.length(2)
177-
expect(providers.map((p) => p.id.toB58String())).to.have.members([
178-
bootstrapId.id,
179-
selfId.toB58String()
180-
])
181-
cb()
182-
}
183-
], done)
135+
it('should be able to specify a maxTimeout', async () => {
136+
const opts = delegateNode.apiAddr.toOptions()
137+
const routing = new DelegatedContentRouting(selfId, {
138+
protocol: 'http',
139+
port: opts.port,
140+
host: opts.host
141+
})
142+
143+
const cid = new CID('QmS4ustL54uo8FzR9455qaxZwuMiUhyvMcX9Ba8nUH4uVv')
144+
const providers = await all(routing.findProviders(cid, { maxTimeout: 5e3 }))
145+
146+
expect(providers.map((p) => p.id.toB58String())).to.include(bootstrapId.id, 'Did not include bootstrap node')
184147
})
185148
})
186149

187150
describe('provide', () => {
188-
it('should be able to register as a content provider to the delegate node', function (done) {
151+
it('should be able to register as a content provider to the delegate node', async () => {
189152
let contentRouter
190153
let cid
191154

192-
waterfall([
193-
(cb) => {
194-
const opts = delegatedNode.apiAddr.toOptions()
195-
contentRouter = new DelegatedContentRouting(selfId, {
196-
protocol: 'http',
197-
port: opts.port,
198-
host: opts.host
199-
})
200-
201-
selfNode.api.add(Buffer.from(`hello-${Math.random()}`), cb)
202-
},
203-
(res, cb) => {
204-
cid = new CID(res[0].hash)
205-
contentRouter.provide(cid, cb)
206-
},
207-
(cb) => {
208-
delegatedNode.api.dht.findProvs(cid, cb)
209-
},
210-
(providers, cb) => {
211-
const providerIds = providers.map(p => p.id.toB58String())
212-
// The delegate should be a provider
213-
expect(providerIds).to.have.members([
214-
selfId.toB58String(),
215-
delegatedId.toB58String()
216-
])
217-
cb()
218-
}
219-
], done)
155+
const opts = delegateNode.apiAddr.toOptions()
156+
contentRouter = new DelegatedContentRouting(selfId, {
157+
protocol: 'http',
158+
port: opts.port,
159+
host: opts.host
160+
})
161+
162+
const res = await selfNode.api.add(Buffer.from(`hello-${Math.random()}`))
163+
cid = new CID(res[0].hash)
164+
await contentRouter.provide(cid)
165+
const providers = await delegateNode.api.dht.findProvs(cid.toBaseEncodedString())
166+
167+
// We are hosting the file, validate we're the provider
168+
expect(providers.map((p) => p.id.toB58String())).to.include(selfId.toB58String(), 'Did not include self node')
220169
})
221170
})
222171
})

0 commit comments

Comments
 (0)
Please sign in to comment.