Skip to content

Commit 93e8ad0

Browse files
committed
feat: support socket timeouts on a per-connection level
1 parent 2bd17a6 commit 93e8ad0

File tree

4 files changed

+54
-2
lines changed

4 files changed

+54
-2
lines changed

lib/cmap/connection.js

+12-2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,16 @@ class Connection extends EventEmitter {
5151
this.emit('close');
5252
});
5353

54+
stream.on('timeout', () => {
55+
this.closed = true;
56+
this[kQueue].forEach(op =>
57+
op.cb(new MongoNetworkError(`connection ${this.id} to ${this.address} timed out`))
58+
);
59+
this[kQueue].clear();
60+
61+
this.emit('close');
62+
});
63+
5464
// hook the message stream up to the passed in stream
5565
stream.pipe(this[kMessageStream]);
5666
this[kMessageStream].pipe(stream);
@@ -159,7 +169,7 @@ function messageHandler(conn) {
159169

160170
const callback = operationDescription.cb;
161171
if (operationDescription.socketTimeoutOverride) {
162-
this[kStream].setSocketTimeout(this.socketTimeout);
172+
conn[kStream].setTimeout(conn.socketTimeout);
163173
}
164174

165175
try {
@@ -230,7 +240,7 @@ function write(command, options, callback) {
230240

231241
if (typeof options.socketTimeout === 'number') {
232242
operationDescription.socketTimeoutOverride = true;
233-
this[kStream].setSocketTimeout(options.socketTimeout);
243+
this[kStream].setTimeout(options.socketTimeout);
234244
}
235245

236246
// if command monitoring is enabled we need to modify the callback here

lib/cmap/connection_pool.js

+2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ const VALID_POOL_OPTIONS = new Set([
4242
'port',
4343
'bson',
4444
'connectionType',
45+
'monitorCommands',
46+
'socketTimeout',
4547

4648
// spec options
4749
'maxPoolSize',

test/functional/cmap/connection.test.js

+15
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,19 @@ describe('Connection', function() {
4949
});
5050
});
5151
});
52+
53+
it('should support socket timeouts', function(done) {
54+
const connectOptions = Object.assign({
55+
host: '240.0.0.1',
56+
connectionType: Connection,
57+
bson: new BSON(),
58+
connectionTimeout: 500
59+
});
60+
61+
connect(connectOptions, err => {
62+
expect(err).to.exist;
63+
expect(err).to.match(/timed out/);
64+
done();
65+
});
66+
});
5267
});

test/unit/cmap/connection_pool.test.js

+25
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,31 @@ describe('Connection Pool', function() {
8787
});
8888
});
8989

90+
it('should propagate socket timeouts to connections', function(done) {
91+
server.setMessageHandler(request => {
92+
const doc = request.document;
93+
if (doc.ismaster) {
94+
request.reply(mock.DEFAULT_ISMASTER_36);
95+
} else {
96+
// blackhole other requests
97+
}
98+
});
99+
100+
const pool = new ConnectionPool(
101+
Object.assign({ bson: new BSON(), maxPoolSize: 1, socketTimeout: 500 }, server.address())
102+
);
103+
104+
pool.withConnection((err, conn, cb) => {
105+
conn.command('admin.$cmd', { ping: 1 }, (err, result) => {
106+
expect(err).to.exist;
107+
expect(result).to.not.exist;
108+
expect(err).to.match(/timed out/);
109+
cb();
110+
});
111+
}, () => pool.close(done));
112+
});
113+
114+
90115
describe('withConnection', function() {
91116
it('should manage a connection for a successful operation', function(done) {
92117
server.setMessageHandler(request => {

0 commit comments

Comments
 (0)