Skip to content

Commit

Permalink
fix: awaitable isMaster timeout must respect connectTimeoutMS (#2627)
Browse files Browse the repository at this point in the history
  • Loading branch information
emadum authored Dec 1, 2020
1 parent a827807 commit b365c50
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 10 deletions.
23 changes: 13 additions & 10 deletions lib/core/sdam/monitor.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,16 +200,19 @@ function checkServer(monitor, callback) {
const topologyVersion = monitor[kServer].description.topologyVersion;
const isAwaitable = topologyVersion != null;

const cmd = isAwaitable
? { ismaster: true, maxAwaitTimeMS, topologyVersion: makeTopologyVersion(topologyVersion) }
: { ismaster: true };

const options = isAwaitable
? { socketTimeout: connectTimeoutMS + maxAwaitTimeMS, exhaustAllowed: true }
: { socketTimeout: connectTimeoutMS };

if (isAwaitable && monitor[kRTTPinger] == null) {
monitor[kRTTPinger] = new RTTPinger(monitor[kCancellationToken], monitor.connectOptions);
const cmd = { ismaster: true };
const options = { socketTimeout: connectTimeoutMS };

if (isAwaitable) {
cmd.maxAwaitTimeMS = maxAwaitTimeMS;
cmd.topologyVersion = makeTopologyVersion(topologyVersion);
if (connectTimeoutMS) {
options.socketTimeout = connectTimeoutMS + maxAwaitTimeMS;
}
options.exhaustAllowed = true;
if (monitor[kRTTPinger] == null) {
monitor[kRTTPinger] = new RTTPinger(monitor[kCancellationToken], monitor.connectOptions);
}
}

monitor[kConnection].command('admin.$cmd', cmd, options, (err, result) => {
Expand Down
58 changes: 58 additions & 0 deletions test/functional/mongo_client_options.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
const test = require('./shared').assert;
const setupDatabase = require('./shared').setupDatabase;
const expect = require('chai').expect;
const sinon = require('sinon');
const Connection = require('../../lib/cmap/connection').Connection;

describe('MongoClient Options', function() {
before(function() {
Expand Down Expand Up @@ -110,6 +112,62 @@ describe('MongoClient Options', function() {
});
});

it('must respect an infinite connectTimeoutMS for the streaming protocol', {
metadata: { requires: { topology: 'replicaset', mongodb: '>= 4.4' } },
test: function(done) {
if (!this.configuration.usingUnifiedTopology()) return done();
const client = this.configuration.newClient({
connectTimeoutMS: 0,
heartbeatFrequencyMS: 500
});
client.connect(err => {
expect(err).to.not.exist;
const stub = sinon.stub(Connection.prototype, 'command').callsFake(function() {
const args = Array.prototype.slice.call(arguments);
const ns = args[0];
const command = args[1];
const options = args[2];
if (ns === 'admin.$cmd' && command.ismaster && options.exhaustAllowed) {
stub.restore();
expect(options)
.property('socketTimeout')
.to.equal(0);
client.close(done);
}
stub.wrappedMethod.apply(this, args);
});
});
}
});

it('must respect a finite connectTimeoutMS for the streaming protocol', {
metadata: { requires: { topology: 'replicaset', mongodb: '>= 4.4' } },
test: function(done) {
if (!this.configuration.usingUnifiedTopology()) return done();
const client = this.configuration.newClient({
connectTimeoutMS: 10,
heartbeatFrequencyMS: 500
});
client.connect(err => {
expect(err).to.not.exist;
const stub = sinon.stub(Connection.prototype, 'command').callsFake(function() {
const args = Array.prototype.slice.call(arguments);
const ns = args[0];
const command = args[1];
const options = args[2];
if (ns === 'admin.$cmd' && command.ismaster && options.exhaustAllowed) {
stub.restore();
expect(options)
.property('socketTimeout')
.to.equal(510);
client.close(done);
}
stub.wrappedMethod.apply(this, args);
});
});
}
});

/**
* @ignore
*/
Expand Down

0 comments on commit b365c50

Please sign in to comment.