Skip to content

Commit 4fc2904

Browse files
committed
feat(disconnect): now takes a callback to let you know after disconnect finishes
BREAKING CHANGE: callback is required in disconnect method
1 parent 2e2d5ee commit 4fc2904

File tree

2 files changed

+76
-8
lines changed

2 files changed

+76
-8
lines changed

index.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,16 +114,18 @@ class Elector extends EventEmitter {
114114
)
115115
}
116116

117-
disconnect () {
117+
disconnect (callback) {
118118
debug('disconnecting')
119119
this.disconnecting = true
120120
this.client.remove(`${this.electionPath}/${this.id}`, error => {
121121
if (this.ownsClient) {
122122
this.client.close()
123123
}
124124
if (error) {
125-
return debug(error)
125+
debug(error)
126+
return callback(error)
126127
}
128+
callback(null)
127129
})
128130
}
129131
}

test/index.js

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,27 @@ const _ = require('lodash')
88
const assert = require('assert')
99
const uuid = require('uuid')
1010
const zookeeper = require('node-zookeeper-client')
11+
const listeners = ['leader', 'follower']
1112

1213
describe('Elector', function () {
1314
let electors = []
1415

15-
afterEach(function () {
16-
for (let elector of electors) {
17-
elector.disconnect()
18-
}
16+
afterEach(function (done) {
17+
async.each(
18+
electors,
19+
function (elector, callback) {
20+
elector.removeAllListeners(listeners)
21+
if (elector.disconnecting) {
22+
return callback(null)
23+
}
24+
25+
elector.disconnect(callback)
26+
if (!elector.ownsClient) {
27+
elector.client.close()
28+
}
29+
},
30+
done
31+
)
1932
})
2033

2134
it('should elect one node out of the five as leader', function (done) {
@@ -33,6 +46,59 @@ describe('Elector', function () {
3346
})
3447
})
3548

49+
it('should still have one leader after some nodes leave', function (done) {
50+
electors = _.times(5, createElector)
51+
52+
assert(electors.length, 5)
53+
54+
const leaders = []
55+
const followers = []
56+
57+
async.series(
58+
[
59+
function (callback) {
60+
connectAndListen(electors, leaders, followers, function (error) {
61+
assert.equal(leaders.length, 1)
62+
assert.equal(followers.length, 4)
63+
callback(error)
64+
})
65+
},
66+
67+
function (callback) {
68+
const disconnectNodes = _.sampleSize(electors, 2)
69+
async.each(
70+
disconnectNodes,
71+
function (elector, callback) {
72+
elector.removeAllListeners(listeners)
73+
elector.disconnect(callback)
74+
},
75+
callback
76+
)
77+
}
78+
],
79+
function () {
80+
let leaders = 0
81+
let followers = 0
82+
let disconnected = 0
83+
for (let elector of electors) {
84+
if (elector.isLeader) {
85+
leaders++
86+
} else {
87+
followers++
88+
}
89+
if (elector.disconnecting) {
90+
disconnected++
91+
}
92+
}
93+
94+
assert.equal(leaders, 1)
95+
assert.equal(followers, 4)
96+
assert.equal(disconnected, 2)
97+
done()
98+
}
99+
)
100+
})
101+
36102
it('should take an existing zookeeper client', function (done) {
37103
const electionPath = '/' + uuid.v4()
38104
electors = _.times(5, function () {
@@ -70,8 +136,8 @@ function connectAndListen (electors, leaders, followers, callback) {
70136
}
71137
callback(null)
72138
}
73-
elector.on('leader', cb)
74-
elector.on('follower', cb)
139+
elector.once('leader', cb)
140+
elector.once('follower', cb)
75141
elector.on('error', callback)
76142
},
77143
callback

0 commit comments

Comments
 (0)