Skip to content

Commit 8047fb7

Browse files
authored
fix: start and stop error callback (#316)
* fix: ensure start and stop callbacks are called
1 parent c4cab00 commit 8047fb7

File tree

4 files changed

+62
-6
lines changed

4 files changed

+62
-6
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
"libp2p-websockets": "~0.12.0",
5555
"mafmt": "^6.0.2",
5656
"multiaddr": "^6.0.2",
57+
"once": "^1.4.0",
5758
"peer-book": "~0.9.0",
5859
"peer-id": "~0.12.0",
5960
"peer-info": "~0.15.0"

src/index.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const Ping = require('libp2p-ping')
1717
const WebSockets = require('libp2p-websockets')
1818
const ConnectionManager = require('libp2p-connection-manager')
1919

20+
const { emitFirst } = require('./util')
2021
const peerRouting = require('./peer-routing')
2122
const contentRouting = require('./content-routing')
2223
const dht = require('./dht')
@@ -194,7 +195,7 @@ class Node extends EventEmitter {
194195
* @returns {void}
195196
*/
196197
start (callback = () => {}) {
197-
this.once('start', callback)
198+
emitFirst(this, ['error', 'start'], callback)
198199
this.state('start')
199200
}
200201

@@ -205,7 +206,7 @@ class Node extends EventEmitter {
205206
* @returns {void}
206207
*/
207208
stop (callback = () => {}) {
208-
this.once('stop', callback)
209+
emitFirst(this, ['error', 'stop'], callback)
209210
this.state('stop')
210211
}
211212

@@ -473,8 +474,9 @@ class Node extends EventEmitter {
473474
this._switch.stop(cb)
474475
},
475476
(cb) => {
476-
// Ensures idempotent restarts
477-
this._switch.transport.removeAll(cb)
477+
// Ensures idempotent restarts, ignore any errors
478+
// from removeAll, they're not useful at this point
479+
this._switch.transport.removeAll(() => cb())
478480
}
479481
], (err) => {
480482
if (err) {

src/util/index.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
'use strict'
2+
const once = require('once')
3+
4+
/**
5+
* Registers `handler` to each event in `events`. The `handler`
6+
* will only be called for the first event fired, at which point
7+
* the `handler` will be removed as a listener.
8+
*
9+
* Ensures `handler` is only called once.
10+
*
11+
* @example
12+
* // will call `callback` when `start` or `error` is emitted by `this`
13+
* emitFirst(this, ['error', 'start'], callback)
14+
*
15+
* @private
16+
* @param {EventEmitter} emitter The emitter to listen on
17+
* @param {Array<string>} events The events to listen for
18+
* @param {function(*)} handler The handler to call when an event is triggered
19+
* @returns {void}
20+
*/
21+
function emitFirst (emitter, events, handler) {
22+
handler = once(handler)
23+
events.forEach((e) => {
24+
emitter.once(e, (...args) => {
25+
events.forEach((ev) => {
26+
emitter.removeListener(ev, handler)
27+
})
28+
handler.apply(emitter, args)
29+
})
30+
})
31+
}
32+
33+
module.exports.emitFirst = emitFirst

test/fsm.spec.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ describe('libp2p state machine (fsm)', () => {
2626
})
2727
afterEach(() => {
2828
node.removeAllListeners()
29+
sinon.restore()
2930
})
3031
after((done) => {
3132
node.stop(done)
@@ -64,6 +65,23 @@ describe('libp2p state machine (fsm)', () => {
6465
node.start()
6566
})
6667

68+
it('should callback with an error when it occurs on stop', (done) => {
69+
const error = new Error('some error starting')
70+
node.once('start', () => {
71+
node.once('error', (err) => {
72+
expect(err).to.eql(error).mark()
73+
})
74+
node.stop((err) => {
75+
expect(err).to.eql(error).mark()
76+
})
77+
})
78+
79+
expect(2).checks(done)
80+
81+
sinon.stub(node._switch, 'stop').callsArgWith(0, error)
82+
node.start()
83+
})
84+
6785
it('should noop when starting a started node', (done) => {
6886
node.once('start', () => {
6987
node.state.on('STARTING', () => {
@@ -116,9 +134,11 @@ describe('libp2p state machine (fsm)', () => {
116134
throw new Error('should not start')
117135
})
118136

119-
expect(2).checks(done)
137+
expect(3).checks(done)
120138

121-
node.start()
139+
node.start((err) => {
140+
expect(err).to.eql(error).mark()
141+
})
122142
})
123143

124144
it('should not dial when the node is stopped', (done) => {

0 commit comments

Comments
 (0)