From f2091603c708d363e5ac6371a437caefb80205a8 Mon Sep 17 00:00:00 2001 From: Matt Broadstone Date: Wed, 23 Oct 2019 11:15:37 -0400 Subject: [PATCH] fix(replset): don't leak servers failing to connect The change to include all connecting servers in the local `connectingServers` array lead to a "server leak" for nodes that we are not able to connect to. Now we track them, and only add new ones on a successful reconnect attempt. NODE-2270 --- lib/core/topologies/replset.js | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/lib/core/topologies/replset.js b/lib/core/topologies/replset.js index 89403ea4ae..3039c56979 100644 --- a/lib/core/topologies/replset.js +++ b/lib/core/topologies/replset.js @@ -277,15 +277,26 @@ function rexecuteOperations(self) { } function connectNewServers(self, servers, callback) { + // No new servers + if (servers.length === 0) { + return callback(); + } + // Count lefts var count = servers.length; var error = null; + function done() { + count = count - 1; + if (count === 0) { + callback(error); + } + } + // Handle events var _handleEvent = function(self, event) { return function(err) { var _self = this; - count = count - 1; // Destroyed if (self.state === DESTROYED || self.state === UNREFERENCED) { @@ -332,17 +343,10 @@ function connectNewServers(self, servers, callback) { // Rexecute any stalled operation rexecuteOperations(self); - - // Are we done finish up callback - if (count === 0) { - callback(error); - } + done(); }; }; - // No new servers - if (count === 0) return callback(); - // Execute method function execute(_server, i) { setTimeout(function() { @@ -351,6 +355,18 @@ function connectNewServers(self, servers, callback) { return; } + // remove existing connecting server if it's failed to connect, otherwise + // wait for that server to connect + const existingServerIdx = self.s.connectingServers.findIndex(s => s.name === _server); + if (existingServerIdx >= 0) { + const connectingServer = self.s.connectingServers[existingServerIdx]; + connectingServer.destroy({ force: true }); + + self.s.connectingServers.splice(existingServerIdx, 1); + done(); + return; + } + // Create a new server instance var server = new Server( Object.assign({}, self.s.options, {