Skip to content

Commit

Permalink
feat: add strategies to discovery configs
Browse files Browse the repository at this point in the history
  • Loading branch information
jacobheun committed Apr 4, 2019
1 parent 4c18f09 commit 892c1d3
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 33 deletions.
4 changes: 3 additions & 1 deletion src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ const transport = s.union([

const optionsSchema = s(
{
connectionManager: 'object?',
connectionManager: s('object', {
minPeers: 25
}),
datastore: 'object?',
peerInfo: 'object',
peerBook: 'object?',
Expand Down
92 changes: 60 additions & 32 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ const pubsub = require('./pubsub')
const getPeerInfo = require('./get-peer-info')
const validateConfig = require('./config').validate

const DISCOVERY_STRATEGIES = {
ALL: 0, // All peers
LOW: 1 // When below the ConnectionManager watermark
}

const notStarted = (action, state) => {
return errCode(
new Error(`libp2p cannot ${action} when not started; state is ${state}`),
Expand All @@ -45,7 +50,7 @@ class Node extends EventEmitter {
super()
// validateConfig will ensure the config is correct,
// and add default values where appropriate
_options = validateConfig(_options)
this._options = validateConfig(_options)

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

// create the switch, and listen for errors
this._switch = new Switch(this.peerInfo, this.peerBook, _options.switch)
this._switch = new Switch(this.peerInfo, this.peerBook, this._options.switch)
this._switch.on('error', (...args) => this.emit('error', ...args))

this.stats = this._switch.stats
this.connectionManager = new ConnectionManager(this, _options.connectionManager)
this.connectionManager = new ConnectionManager(this, this._options.connectionManager)

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

// all transports need to be setup before discover starts
if (this._modules.peerDiscovery) {
each(this._modules.peerDiscovery, (D, _cb) => {
let config = {}

if (D.tag &&
this._config.peerDiscovery &&
this._config.peerDiscovery[D.tag]) {
config = this._config.peerDiscovery[D.tag]
}

// If not configured to be enabled/disabled then enable by default
const enabled = config.enabled == null ? true : config.enabled

// If enabled then start it
if (enabled) {
let d

if (typeof D === 'function') {
d = new D(Object.assign({}, config, { peerInfo: this.peerInfo }))
} else {
d = D
}

d.on('peer', (peerInfo) => this.emit('peer:discovery', peerInfo))
this._discovery.push(d)
d.start(_cb)
} else {
_cb()
}
}, cb)
this._setupPeerDiscovery(cb)
} else {
cb()
}
Expand Down Expand Up @@ -473,6 +450,57 @@ class Node extends EventEmitter {
this.state('done')
})
}

/**
* Initializes and starts peer discovery services
*
* @private
* @param {function(Error)} callback
*/
_setupPeerDiscovery (callback) {
const minPeers = this._options.connectionManager.minPeers || 0
for (const DiscoveryService of this._modules.peerDiscovery) {
let config = {
enabled: true // on by default
}

if (DiscoveryService.tag &&
this._config.peerDiscovery &&
this._config.peerDiscovery[DiscoveryService.tag]) {
config = this._config.peerDiscovery[DiscoveryService.tag]
}

if (config.enabled) {
let discoveryService

if (typeof DiscoveryService === 'function') {
discoveryService = new DiscoveryService(Object.assign({}, config, { peerInfo: this.peerInfo }))
} else {
discoveryService = DiscoveryService
}

discoveryService.on('peer', (peerInfo) => {
switch (config.strategy) {
case DISCOVERY_STRATEGIES.LOW:
const peerConns = Object.keys(this._switch.connection.connections).length
if (peerConns < minPeers || peerConns === 0) {
this.emit('peer:discovery', peerInfo)
}
break
default:
this.emit('peer:discovery', peerInfo)
}
})

this._discovery.push(discoveryService)
}
}

each(this._discovery, (d, cb) => {
d.start(cb)
}, callback)
}
}

module.exports = Node
module.exports.DISCOVERY_STRATEGIES = DISCOVERY_STRATEGIES
6 changes: 6 additions & 0 deletions test/config.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ describe('configuration', () => {

const expected = {
peerInfo,
connectionManager: {
minPeers: 25
},
modules: {
transport: [ WS ],
peerDiscovery: [ Bootstrap ],
Expand Down Expand Up @@ -180,6 +183,9 @@ describe('configuration', () => {
}
const expected = {
peerInfo,
connectionManager: {
minPeers: 25
},
modules: {
transport: [WS],
dht: DHT
Expand Down
53 changes: 53 additions & 0 deletions test/peer-discovery.node.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const sinon = require('sinon')
const signalling = require('libp2p-webrtc-star/src/sig-server')
const parallel = require('async/parallel')
const crypto = require('crypto')
const { DISCOVERY_STRATEGIES } = require('../src')

const createNode = require('./utils/create-node')
const echo = require('./utils/echo')
Expand Down Expand Up @@ -419,4 +420,56 @@ describe('peer discovery', () => {
})
})
})

describe('discovery strategies', () => {
describe('low', () => {
setup({
connectionManager: {
minPeers: 1
},
config: {
peerDiscovery: {
mdns: {
enabled: false
},
webRTCStar: {
enabled: false
},
bootstrap: {
enabled: true,
strategy: DISCOVERY_STRATEGIES.LOW,
list: []
}
},
dht: {
enabled: false
}
}
})

it('should only emit when the peer count is below the low watermark', (done) => {
let expectedPeers = [
nodeB.peerInfo
]
let actualPeers = []
const bootstrap = nodeA._discovery[0]

nodeA.on('peer:discovery', (peerInfo) => {
actualPeers.push(peerInfo)

// Connect, which brings us to our low watermark
nodeA.dial(peerInfo, () => {
// This second emit should not trigger discovery
bootstrap.emit('peer', nodeC.peerInfo)

expect(expectedPeers).to.eql(actualPeers)
nodeA.removeAllListeners('peer:discovery')
done()
})
})

bootstrap.emit('peer', nodeB.peerInfo)
})
})
})
})
1 change: 1 addition & 0 deletions test/utils/bundle-browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class Node extends libp2p {
},
bootstrap: {
interval: 10000,
strategy: libp2p.DISCOVERY_STRATEGIES.LOW,
enabled: false,
list: _options.boostrapList
}
Expand Down
1 change: 1 addition & 0 deletions test/utils/bundle-nodejs.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class Node extends libp2p {
},
bootstrap: {
interval: 10000,
strategy: libp2p.DISCOVERY_STRATEGIES.LOW,
enabled: false,
list: _options.bootstrapList
}
Expand Down

0 comments on commit 892c1d3

Please sign in to comment.