Skip to content

Commit fb3eb76

Browse files
authored
fix(cluster): quit() ignores errors caused by disconnected connection (#720)
1 parent 16643e2 commit fb3eb76

File tree

3 files changed

+74
-6
lines changed

3 files changed

+74
-6
lines changed

lib/cluster/index.ts

+10-5
Original file line numberDiff line numberDiff line change
@@ -267,11 +267,16 @@ class Cluster extends EventEmitter {
267267
return ret
268268
}
269269
return asCallback(
270-
Promise.all(this.nodes().map(function (node) {
271-
return node.quit()
272-
})).then(function () {
273-
return 'OK'
274-
}),
270+
Promise.all(this.nodes().map((node) => (
271+
node.quit().catch((err) => {
272+
// Ignore the error caused by disconnecting since
273+
// we're disconnecting...
274+
if (err.message === CONNECTION_CLOSED_ERROR_MSG) {
275+
return 'OK'
276+
}
277+
throw err
278+
})
279+
))).then(() => 'OK'),
275280
callback
276281
)
277282
}

test/functional/cluster/quit.js

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
describe('cluster:quit', () => {
2+
it('quit successfully when server is disconnecting', (done) => {
3+
const slotTable = [
4+
[0, 1000, ['127.0.0.1', 30001]],
5+
[1001, 16383, ['127.0.0.1', 30002]]
6+
]
7+
const server = new MockServer(30001, (argv, c) => {
8+
if (argv[0] === 'quit') {
9+
c.destroy()
10+
}
11+
}, slotTable)
12+
new MockServer(30002, (argv, c) => {
13+
if (argv[0] === 'quit') {
14+
c.destroy()
15+
}
16+
}, slotTable)
17+
18+
const cluster = new Redis.Cluster([
19+
{ host: '127.0.0.1', port: '30001' }
20+
])
21+
cluster.on('ready', () => {
22+
server.disconnect()
23+
cluster.quit((err, res) => {
24+
expect(err).to.eql(null)
25+
expect(res).to.eql('OK')
26+
done()
27+
})
28+
})
29+
})
30+
31+
it('failed when quit returns error', function (done) {
32+
const ERROR_MESSAGE = 'quit random error'
33+
const slotTable = [
34+
[0, 1000, ['127.0.0.1', 30001]],
35+
[1001, 16383, ['127.0.0.1', 30002]]
36+
]
37+
new MockServer(30001, function (argv, c) {
38+
if (argv[0] === 'quit') {
39+
return new Error(ERROR_MESSAGE)
40+
}
41+
}, slotTable)
42+
new MockServer(30002, function (argv, c) {
43+
if (argv[0] === 'quit') {
44+
c.destroy()
45+
}
46+
}, slotTable)
47+
48+
const cluster = new Redis.Cluster([
49+
{ host: '127.0.0.1', port: '30001' }
50+
])
51+
cluster.on('ready', () => {
52+
cluster.quit((err) => {
53+
expect(err.message).to.eql(ERROR_MESSAGE)
54+
done()
55+
})
56+
})
57+
})
58+
})

test/helpers/mock_server.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,12 @@ afterEach(function (done) {
2929
}
3030
});
3131

32-
function MockServer(port, handler) {
32+
function MockServer(port, handler, slotTable) {
3333
EventEmitter.call(this);
3434

3535
this.port = port;
3636
this.handler = handler;
37+
this.slotTable = slotTable;
3738

3839
this.clients = [];
3940

@@ -60,6 +61,10 @@ MockServer.prototype.connect = function () {
6061
if (reply.length === 3 && reply[0].toLowerCase() === 'client' && reply[1].toLowerCase() === 'setname') {
6162
c._connectionName = reply[2]
6263
}
64+
if (_this.slotTable && reply.length === 2 && reply[0].toLowerCase() === 'cluster' && reply[1].toLowerCase() === 'slots') {
65+
_this.write(c, _this.slotTable)
66+
return
67+
}
6368
_this.write(c, _this.handler && _this.handler(reply, c));
6469
},
6570
returnError: function () { }

0 commit comments

Comments
 (0)