Skip to content

Commit 2e2d5ee

Browse files
committed
feat(zookeeper): add ability to use passed in zookeeper client
1 parent b9a6e32 commit 2e2d5ee

File tree

4 files changed

+75
-32
lines changed

4 files changed

+75
-32
lines changed

README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,23 @@ const Elector = require('elector')
2323

2424
const elector = new Elector({host: 'localhost:2818'})
2525

26+
// alternatively pass in zookeeper client
27+
// const elector = new Elector(new zookeeper.createClient('localhost:2818'))
28+
2629
// connects to zookeeper and starts the election process
2730
elector.connect()
2831

2932
elector.on('leader', function () {
30-
console.log('I am the supreme leader worship me!');
33+
console.log('I am the supreme leader worship me!')
3134
})
3235

3336
elector.on('follower', function () {
34-
console.log('I am but a lowly follower :(');
37+
console.log('I am but a lowly follower :(')
3538
})
3639

3740
// leave the election and closes zookeeper connection
38-
elector.leave();
39-
41+
// do this to leave the election quickly
42+
// elector.disconnect()
4043
```
4144

4245

index.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,26 @@ class Elector extends EventEmitter {
1111
super()
1212
this.id = null
1313
this.electionPath = electionPath
14-
this.client = zookeeper.createClient(zkOptions.host)
14+
15+
if (this._isZkClient(zkOptions)) {
16+
this.client = zkOptions
17+
} else {
18+
this.client = zookeeper.createClient(zkOptions.host)
19+
this.ownsClient = true
20+
}
1521
this.client.once('connected', () => this._onConnect())
1622
}
1723

1824
connect () {
1925
this.client.connect()
2026
}
2127

28+
_isZkClient (client) {
29+
return (
30+
_.isObject(client) && 'connectionManager' in client && 'close' in client
31+
)
32+
}
33+
2234
_onConnect () {
2335
debug('connected!')
2436
async.waterfall(
@@ -106,7 +118,9 @@ class Elector extends EventEmitter {
106118
debug('disconnecting')
107119
this.disconnecting = true
108120
this.client.remove(`${this.electionPath}/${this.id}`, error => {
109-
this.client.close()
121+
if (this.ownsClient) {
122+
this.client.close()
123+
}
110124
if (error) {
111125
return debug(error)
112126
}

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"main": "index.js",
66
"scripts": {
77
"test": "standard && docker-compose up -d && mocha",
8-
"format": "prettier-standard '*.js'",
8+
"format": "prettier-standard '*.js' 'test/*js'",
99
"semantic-release": "semantic-release pre && npm publish && semantic-release post"
1010
},
1111
"repository": {
@@ -42,7 +42,7 @@
4242
},
4343
"lint-staged": {
4444
"linters": {
45-
"src/**/*.js": [
45+
"**/*.js": [
4646
"prettier-standard",
4747
"git add"
4848
]

test/index.js

Lines changed: 50 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ const Elector = require('../')
66
const async = require('async')
77
const _ = require('lodash')
88
const assert = require('assert')
9+
const uuid = require('uuid')
10+
const zookeeper = require('node-zookeeper-client')
911

1012
describe('Elector', function () {
1113
let electors = []
@@ -24,34 +26,58 @@ describe('Elector', function () {
2426
const leaders = []
2527
const followers = []
2628

27-
async.each(
28-
electors,
29-
function (elector, callback) {
30-
elector.connect()
31-
function cb (error) {
32-
if (error) {
33-
return callback(error)
34-
}
35-
if (this.isLeader) {
36-
leaders.push(this.id)
37-
} else {
38-
followers.push(this.id)
39-
}
40-
callback(null)
41-
}
42-
elector.on('leader', cb)
43-
elector.on('follower', cb)
44-
elector.on('error', callback)
45-
},
46-
function (error) {
47-
assert.equal(leaders.length, 1)
48-
assert.equal(followers.length, 4)
49-
done(error)
29+
connectAndListen(electors, leaders, followers, function (error) {
30+
assert.equal(leaders.length, 1)
31+
assert.equal(followers.length, 4)
32+
done(error)
33+
})
34+
})
35+
36+
it('should take an existing zookeeper client', function (done) {
37+
const electionPath = '/' + uuid.v4()
38+
electors = _.times(5, function () {
39+
const client = zookeeper.createClient('localhost:2181')
40+
return new Elector(client, electionPath)
41+
})
42+
43+
const leaders = []
44+
const followers = []
45+
46+
connectAndListen(electors, leaders, followers, function (error) {
47+
assert.equal(leaders.length, 1)
48+
assert.equal(followers.length, 4)
49+
for (let elector of electors) {
50+
assert.equal(elector.ownsClient, undefined)
5051
}
51-
)
52+
done(error)
53+
})
5254
})
5355
})
5456

57+
function connectAndListen (electors, leaders, followers, callback) {
58+
async.each(
59+
electors,
60+
function (elector, callback) {
61+
elector.connect()
62+
function cb (error) {
63+
if (error) {
64+
return callback(error)
65+
}
66+
if (this.isLeader) {
67+
leaders.push(this.id)
68+
} else {
69+
followers.push(this.id)
70+
}
71+
callback(null)
72+
}
73+
elector.on('leader', cb)
74+
elector.on('follower', cb)
75+
elector.on('error', callback)
76+
},
77+
callback
78+
)
79+
}
80+
5581
function createElector () {
5682
return new Elector({ host: 'localhost:2181' })
5783
}

0 commit comments

Comments
 (0)