Skip to content

Commit

Permalink
fix: recover on network error during initial connect
Browse files Browse the repository at this point in the history
  • Loading branch information
mbroadst committed Dec 31, 2019
1 parent d446be5 commit a13dc68
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 8 deletions.
9 changes: 4 additions & 5 deletions lib/core/sdam/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,6 @@ class Server extends EventEmitter {
error: event.failure
})
);

if (this.s.state === STATE_CONNECTING) {
this.emit('error', new MongoNetworkError(event.failure));
this.destroy();
}
});

this[kMonitor].on('serverHeartbeatSucceeded', event => {
Expand Down Expand Up @@ -187,6 +182,10 @@ class Server extends EventEmitter {
* Initiate server connect
*/
connect() {
if (this.s.state !== STATE_CLOSED) {
return;
}

stateTransition(this, STATE_CONNECTING);
this[kMonitor].connect();
}
Expand Down
6 changes: 3 additions & 3 deletions lib/core/sdam/topology.js
Original file line number Diff line number Diff line change
Expand Up @@ -280,9 +280,10 @@ class Topology extends EventEmitter {
const readPreference = options.readPreference || ReadPreference.primary;
this.selectServer(readPreferenceServerSelector(readPreference), options, (err, server) => {
if (err) {
stateTransition(this, STATE_CLOSED);
this.close();

if (typeof callback === 'function') {
callback(err, null);
callback(err);
} else {
this.emit('error', err);
}
Expand All @@ -305,7 +306,6 @@ class Topology extends EventEmitter {
if (typeof callback === 'function') callback(err, this);
};

const STATE_CONNECTING = 1;
if (server.s.state === STATE_CONNECTING) {
server.once('error', errorHandler);
server.once('connect', connectHandler);
Expand Down
41 changes: 41 additions & 0 deletions test/unit/sdam/monitoring.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,47 @@ describe('monitoring', function() {
});
});

it('should recover on error during initial connect', function(done) {
let acceptConnections = false;
mockServer.setMessageHandler(request => {
if (!acceptConnections) {
request.connection.destroy();
return;
}

const doc = request.document;
if (doc.ismaster) {
request.reply(Object.assign({}, mock.DEFAULT_ISMASTER));
} else if (doc.endSessions) {
request.reply({ ok: 1 });
}
});

setTimeout(() => {
acceptConnections = true;
}, 250);

// set `heartbeatFrequencyMS` to 250ms to force a quick monitoring check, and wait 500ms to validate below
const topology = new Topology(mockServer.uri(), { heartbeatFrequencyMS: 250 });
topology.connect(err => {
expect(err).to.not.exist;

setTimeout(() => {
expect(topology)
.property('description')
.property('servers')
.to.have.length(1);

const serverDescription = Array.from(topology.description.servers.values())[0];
expect(serverDescription)
.property('roundTripTime')
.to.be.greaterThan(0);

topology.close(done);
}, 500);
});
});

describe('Monitor', function() {
it('should connect and issue an initial server check', function(done) {
mockServer.setMessageHandler(request => {
Expand Down

0 comments on commit a13dc68

Please sign in to comment.