Skip to content

Commit 892c1d3

Browse files
committed
feat: add strategies to discovery configs
1 parent 4c18f09 commit 892c1d3

File tree

6 files changed

+124
-33
lines changed

6 files changed

+124
-33
lines changed

src/config.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ const transport = s.union([
1515

1616
const optionsSchema = s(
1717
{
18-
connectionManager: 'object?',
18+
connectionManager: s('object', {
19+
minPeers: 25
20+
}),
1921
datastore: 'object?',
2022
peerInfo: 'object',
2123
peerBook: 'object?',

src/index.js

Lines changed: 60 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ const pubsub = require('./pubsub')
2525
const getPeerInfo = require('./get-peer-info')
2626
const validateConfig = require('./config').validate
2727

28+
const DISCOVERY_STRATEGIES = {
29+
ALL: 0, // All peers
30+
LOW: 1 // When below the ConnectionManager watermark
31+
}
32+
2833
const notStarted = (action, state) => {
2934
return errCode(
3035
new Error(`libp2p cannot ${action} when not started; state is ${state}`),
@@ -45,7 +50,7 @@ class Node extends EventEmitter {
4550
super()
4651
// validateConfig will ensure the config is correct,
4752
// and add default values where appropriate
48-
_options = validateConfig(_options)
53+
this._options = validateConfig(_options)
4954

5055
this.datastore = _options.datastore
5156
this.peerInfo = _options.peerInfo
@@ -57,11 +62,11 @@ class Node extends EventEmitter {
5762
this._discovery = [] // Discovery service instances/references
5863

5964
// create the switch, and listen for errors
60-
this._switch = new Switch(this.peerInfo, this.peerBook, _options.switch)
65+
this._switch = new Switch(this.peerInfo, this.peerBook, this._options.switch)
6166
this._switch.on('error', (...args) => this.emit('error', ...args))
6267

6368
this.stats = this._switch.stats
64-
this.connectionManager = new ConnectionManager(this, _options.connectionManager)
69+
this.connectionManager = new ConnectionManager(this, this._options.connectionManager)
6570

6671
// Attach stream multiplexers
6772
if (this._modules.streamMuxer) {
@@ -359,35 +364,7 @@ class Node extends EventEmitter {
359364

360365
// all transports need to be setup before discover starts
361366
if (this._modules.peerDiscovery) {
362-
each(this._modules.peerDiscovery, (D, _cb) => {
363-
let config = {}
364-
365-
if (D.tag &&
366-
this._config.peerDiscovery &&
367-
this._config.peerDiscovery[D.tag]) {
368-
config = this._config.peerDiscovery[D.tag]
369-
}
370-
371-
// If not configured to be enabled/disabled then enable by default
372-
const enabled = config.enabled == null ? true : config.enabled
373-
374-
// If enabled then start it
375-
if (enabled) {
376-
let d
377-
378-
if (typeof D === 'function') {
379-
d = new D(Object.assign({}, config, { peerInfo: this.peerInfo }))
380-
} else {
381-
d = D
382-
}
383-
384-
d.on('peer', (peerInfo) => this.emit('peer:discovery', peerInfo))
385-
this._discovery.push(d)
386-
d.start(_cb)
387-
} else {
388-
_cb()
389-
}
390-
}, cb)
367+
this._setupPeerDiscovery(cb)
391368
} else {
392369
cb()
393370
}
@@ -473,6 +450,57 @@ class Node extends EventEmitter {
473450
this.state('done')
474451
})
475452
}
453+
454+
/**
455+
* Initializes and starts peer discovery services
456+
*
457+
* @private
458+
* @param {function(Error)} callback
459+
*/
460+
_setupPeerDiscovery (callback) {
461+
const minPeers = this._options.connectionManager.minPeers || 0
462+
for (const DiscoveryService of this._modules.peerDiscovery) {
463+
let config = {
464+
enabled: true // on by default
465+
}
466+
467+
if (DiscoveryService.tag &&
468+
this._config.peerDiscovery &&
469+
this._config.peerDiscovery[DiscoveryService.tag]) {
470+
config = this._config.peerDiscovery[DiscoveryService.tag]
471+
}
472+
473+
if (config.enabled) {
474+
let discoveryService
475+
476+
if (typeof DiscoveryService === 'function') {
477+
discoveryService = new DiscoveryService(Object.assign({}, config, { peerInfo: this.peerInfo }))
478+
} else {
479+
discoveryService = DiscoveryService
480+
}
481+
482+
discoveryService.on('peer', (peerInfo) => {
483+
switch (config.strategy) {
484+
case DISCOVERY_STRATEGIES.LOW:
485+
const peerConns = Object.keys(this._switch.connection.connections).length
486+
if (peerConns < minPeers || peerConns === 0) {
487+
this.emit('peer:discovery', peerInfo)
488+
}
489+
break
490+
default:
491+
this.emit('peer:discovery', peerInfo)
492+
}
493+
})
494+
495+
this._discovery.push(discoveryService)
496+
}
497+
}
498+
499+
each(this._discovery, (d, cb) => {
500+
d.start(cb)
501+
}, callback)
502+
}
476503
}
477504

478505
module.exports = Node
506+
module.exports.DISCOVERY_STRATEGIES = DISCOVERY_STRATEGIES

test/config.spec.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ describe('configuration', () => {
7878

7979
const expected = {
8080
peerInfo,
81+
connectionManager: {
82+
minPeers: 25
83+
},
8184
modules: {
8285
transport: [ WS ],
8386
peerDiscovery: [ Bootstrap ],
@@ -180,6 +183,9 @@ describe('configuration', () => {
180183
}
181184
const expected = {
182185
peerInfo,
186+
connectionManager: {
187+
minPeers: 25
188+
},
183189
modules: {
184190
transport: [WS],
185191
dht: DHT

test/peer-discovery.node.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const sinon = require('sinon')
88
const signalling = require('libp2p-webrtc-star/src/sig-server')
99
const parallel = require('async/parallel')
1010
const crypto = require('crypto')
11+
const { DISCOVERY_STRATEGIES } = require('../src')
1112

1213
const createNode = require('./utils/create-node')
1314
const echo = require('./utils/echo')
@@ -419,4 +420,56 @@ describe('peer discovery', () => {
419420
})
420421
})
421422
})
423+
424+
describe('discovery strategies', () => {
425+
describe('low', () => {
426+
setup({
427+
connectionManager: {
428+
minPeers: 1
429+
},
430+
config: {
431+
peerDiscovery: {
432+
mdns: {
433+
enabled: false
434+
},
435+
webRTCStar: {
436+
enabled: false
437+
},
438+
bootstrap: {
439+
enabled: true,
440+
strategy: DISCOVERY_STRATEGIES.LOW,
441+
list: []
442+
}
443+
},
444+
dht: {
445+
enabled: false
446+
}
447+
}
448+
})
449+
450+
it('should only emit when the peer count is below the low watermark', (done) => {
451+
let expectedPeers = [
452+
nodeB.peerInfo
453+
]
454+
let actualPeers = []
455+
const bootstrap = nodeA._discovery[0]
456+
457+
nodeA.on('peer:discovery', (peerInfo) => {
458+
actualPeers.push(peerInfo)
459+
460+
// Connect, which brings us to our low watermark
461+
nodeA.dial(peerInfo, () => {
462+
// This second emit should not trigger discovery
463+
bootstrap.emit('peer', nodeC.peerInfo)
464+
465+
expect(expectedPeers).to.eql(actualPeers)
466+
nodeA.removeAllListeners('peer:discovery')
467+
done()
468+
})
469+
})
470+
471+
bootstrap.emit('peer', nodeB.peerInfo)
472+
})
473+
})
474+
})
422475
})

test/utils/bundle-browser.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class Node extends libp2p {
6969
},
7070
bootstrap: {
7171
interval: 10000,
72+
strategy: libp2p.DISCOVERY_STRATEGIES.LOW,
7273
enabled: false,
7374
list: _options.boostrapList
7475
}

test/utils/bundle-nodejs.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ class Node extends libp2p {
6262
},
6363
bootstrap: {
6464
interval: 10000,
65+
strategy: libp2p.DISCOVERY_STRATEGIES.LOW,
6566
enabled: false,
6667
list: _options.bootstrapList
6768
}

0 commit comments

Comments
 (0)