Skip to content

Commit 3ec49e5

Browse files
committed
fix(pool): flush workItems after next tick to avoid dupe selection
In the event that a timeout occurs and a server instance is drained, the work items were cleared before the server could signal it needed to be cycled. By waiting until the next tick, we can ensure the event makes it to the `Topology`, and the server is removed from consideration for server selection. NODE-2350
1 parent 8fe456b commit 3ec49e5

File tree

2 files changed

+25
-7
lines changed

2 files changed

+25
-7
lines changed

lib/core/connection/connection.js

+14
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,20 @@ class Connection extends EventEmitter {
194194
this.socket.unref();
195195
}
196196

197+
/**
198+
* Flush all work Items on this connection
199+
*
200+
* @param {*} err The error to propagate to the flushed work items
201+
*/
202+
flush(err) {
203+
while (this.workItems.length > 0) {
204+
const workItem = this.workItems.shift();
205+
if (workItem.cb) {
206+
workItem.cb(err);
207+
}
208+
}
209+
}
210+
197211
/**
198212
* Destroy connection
199213
* @method

lib/core/connection/pool.js

+11-7
Original file line numberDiff line numberDiff line change
@@ -251,20 +251,24 @@ function connectionFailureHandler(pool, event, err, conn) {
251251
// Remove the connection
252252
removeConnection(pool, conn);
253253

254-
// Flush all work Items on this connection
255-
while (conn.workItems.length > 0) {
256-
const workItem = conn.workItems.shift();
257-
if (workItem.cb) workItem.cb(err);
258-
}
259-
260-
if (pool.state !== DRAINING && pool.options.legacyCompatMode === false) {
254+
if (
255+
pool.state !== DRAINING &&
256+
pool.state !== DESTROYED &&
257+
pool.options.legacyCompatMode === false
258+
) {
261259
// since an error/close/timeout means pool invalidation in a
262260
// pre-CMAP world, we will issue a custom `drain` event here to
263261
// signal that the server should be recycled
264262
stateTransition(pool, DRAINING);
265263
pool.emit('drain', err);
264+
265+
// wait to flush work items so this server isn't selected again immediately
266+
process.nextTick(() => conn.flush(err));
266267
return;
267268
}
269+
270+
// flush remaining work items
271+
conn.flush(err);
268272
}
269273

270274
// Did we catch a timeout, increment the numberOfConsecutiveTimeouts

0 commit comments

Comments
 (0)