Skip to content

Commit a13dc68

Browse files
committed
fix: recover on network error during initial connect
1 parent d446be5 commit a13dc68

File tree

3 files changed

+48
-8
lines changed

3 files changed

+48
-8
lines changed

lib/core/sdam/server.js

+4-5
Original file line numberDiff line numberDiff line change
@@ -146,11 +146,6 @@ class Server extends EventEmitter {
146146
error: event.failure
147147
})
148148
);
149-
150-
if (this.s.state === STATE_CONNECTING) {
151-
this.emit('error', new MongoNetworkError(event.failure));
152-
this.destroy();
153-
}
154149
});
155150

156151
this[kMonitor].on('serverHeartbeatSucceeded', event => {
@@ -187,6 +182,10 @@ class Server extends EventEmitter {
187182
* Initiate server connect
188183
*/
189184
connect() {
185+
if (this.s.state !== STATE_CLOSED) {
186+
return;
187+
}
188+
190189
stateTransition(this, STATE_CONNECTING);
191190
this[kMonitor].connect();
192191
}

lib/core/sdam/topology.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -280,9 +280,10 @@ class Topology extends EventEmitter {
280280
const readPreference = options.readPreference || ReadPreference.primary;
281281
this.selectServer(readPreferenceServerSelector(readPreference), options, (err, server) => {
282282
if (err) {
283-
stateTransition(this, STATE_CLOSED);
283+
this.close();
284+
284285
if (typeof callback === 'function') {
285-
callback(err, null);
286+
callback(err);
286287
} else {
287288
this.emit('error', err);
288289
}
@@ -305,7 +306,6 @@ class Topology extends EventEmitter {
305306
if (typeof callback === 'function') callback(err, this);
306307
};
307308

308-
const STATE_CONNECTING = 1;
309309
if (server.s.state === STATE_CONNECTING) {
310310
server.once('error', errorHandler);
311311
server.once('connect', connectHandler);

test/unit/sdam/monitoring.test.js

+41
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,47 @@ describe('monitoring', function() {
5858
});
5959
});
6060

61+
it('should recover on error during initial connect', function(done) {
62+
let acceptConnections = false;
63+
mockServer.setMessageHandler(request => {
64+
if (!acceptConnections) {
65+
request.connection.destroy();
66+
return;
67+
}
68+
69+
const doc = request.document;
70+
if (doc.ismaster) {
71+
request.reply(Object.assign({}, mock.DEFAULT_ISMASTER));
72+
} else if (doc.endSessions) {
73+
request.reply({ ok: 1 });
74+
}
75+
});
76+
77+
setTimeout(() => {
78+
acceptConnections = true;
79+
}, 250);
80+
81+
// set `heartbeatFrequencyMS` to 250ms to force a quick monitoring check, and wait 500ms to validate below
82+
const topology = new Topology(mockServer.uri(), { heartbeatFrequencyMS: 250 });
83+
topology.connect(err => {
84+
expect(err).to.not.exist;
85+
86+
setTimeout(() => {
87+
expect(topology)
88+
.property('description')
89+
.property('servers')
90+
.to.have.length(1);
91+
92+
const serverDescription = Array.from(topology.description.servers.values())[0];
93+
expect(serverDescription)
94+
.property('roundTripTime')
95+
.to.be.greaterThan(0);
96+
97+
topology.close(done);
98+
}, 500);
99+
});
100+
});
101+
61102
describe('Monitor', function() {
62103
it('should connect and issue an initial server check', function(done) {
63104
mockServer.setMessageHandler(request => {

0 commit comments

Comments
 (0)