Skip to content

Commit 7e9c5bc

Browse files
committed
feat: support the streaming protocol for topology updates
This ports work from 3.6 to support the following: - `topologyVersion` on all topology updates, including work to ignore stale errors for topology updates - support servers which stream topology updates
1 parent 1a443e7 commit 7e9c5bc

File tree

184 files changed

+17401
-487
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

184 files changed

+17401
-487
lines changed

lib/cmap/connect.js

+8-5
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22
const net = require('net');
33
const tls = require('tls');
44
const { Connection } = require('./connection');
5-
const MongoError = require('../error').MongoError;
6-
const MongoNetworkError = require('../error').MongoNetworkError;
5+
const {
6+
MongoError,
7+
MongoNetworkError,
8+
MongoNetworkTimeoutError
9+
} = require('../error');
710
const { defaultAuthProviders } = require('./auth/defaultAuthProviders');
8-
const AuthContext = require('./auth/auth_provider').AuthContext;
9-
const makeClientMetadata = require('../utils').makeClientMetadata;
11+
const { AuthContext } = require('./auth/auth_provider');
12+
const { makeClientMetadata } = require('../utils');
1013
const {
1114
MAX_SUPPORTED_WIRE_VERSION,
1215
MAX_SUPPORTED_SERVER_VERSION,
@@ -314,7 +317,7 @@ function connectionFailureError(type, err) {
314317
case 'error':
315318
return new MongoNetworkError(err);
316319
case 'timeout':
317-
return new MongoNetworkError(`connection timed out`);
320+
return new MongoNetworkTimeoutError(`connection timed out`);
318321
case 'close':
319322
return new MongoNetworkError(`connection closed`);
320323
case 'cancel':

lib/cmap/connection.js

+16-9
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@ const wp = require('./wire_protocol');
88
const { CommandStartedEvent, CommandFailedEvent, CommandSucceededEvent } = require('./events');
99
const { updateSessionFromResponse } = require('../sessions');
1010
const { uuidV4 } = require('../utils');
11-
const { MongoError, MongoNetworkError, MongoWriteConcernError } = require('../error');
11+
const {
12+
MongoError,
13+
MongoNetworkError,
14+
MongoNetworkTimeoutError,
15+
MongoWriteConcernError
16+
} = require('../error');
1217

1318
const kStream = Symbol('stream');
1419
const kQueue = Symbol('queue');
@@ -72,10 +77,14 @@ class Connection extends EventEmitter {
7277
stream.destroy();
7378
this.closed = true;
7479
this[kQueue].forEach(op =>
75-
op.cb(new MongoNetworkError(`connection ${this.id} to ${this.address} timed out`))
80+
op.cb(
81+
new MongoNetworkTimeoutError(`connection ${this.id} to ${this.address} timed out`, {
82+
beforeHandshake: this[kIsMaster] == null
83+
})
84+
)
7685
);
77-
this[kQueue].clear();
7886

87+
this[kQueue].clear();
7988
this.emit('close');
8089
});
8190

@@ -212,6 +221,7 @@ function messageHandler(conn) {
212221
}
213222

214223
const operationDescription = conn[kQueue].get(message.responseTo);
224+
const callback = operationDescription.cb;
215225

216226
// SERVER-45775: For exhaust responses we should be able to use the same requestId to
217227
// track response, however the server currently synthetically produces remote requests
@@ -220,10 +230,7 @@ function messageHandler(conn) {
220230
if (message.moreToCome) {
221231
// requeue the callback for next synthetic request
222232
conn[kQueue].set(message.requestId, operationDescription);
223-
}
224-
225-
const callback = operationDescription.cb;
226-
if (operationDescription.socketTimeoutOverride) {
233+
} else if (operationDescription.socketTimeoutOverride) {
227234
conn[kStream].setTimeout(conn.socketTimeout);
228235
}
229236

@@ -320,8 +327,8 @@ function write(command, options, callback) {
320327
}
321328

322329
// if command monitoring is enabled we need to modify the callback here
323-
if (this.monitorCommands) {
324-
connection.emit('commandStarted', new CommandStartedEvent(this, command));
330+
if (connection.monitorCommands) {
331+
connection.emit('commandStarted', new CommandStartedEvent(connection, command));
325332

326333
operationDescription.started = process.hrtime();
327334
operationDescription.cb = (err, reply) => {

lib/error.js

+28-2
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ class MongoError extends Error {
105105
}
106106
}
107107

108+
const kBeforeHandshake = Symbol('beforeHandshake');
109+
function isNetworkErrorBeforeHandshake(err) {
110+
return err[kBeforeHandshake] === true;
111+
}
112+
108113
/**
109114
* An error indicating an issue with the network, including TCP
110115
* errors and timeouts.
@@ -115,9 +120,28 @@ class MongoError extends Error {
115120
* @extends MongoError
116121
*/
117122
class MongoNetworkError extends MongoError {
118-
constructor(message) {
123+
constructor(message, options) {
119124
super(message);
120125
this.name = 'MongoNetworkError';
126+
127+
if (options && options.beforeHandshake === true) {
128+
this[kBeforeHandshake] = true;
129+
}
130+
}
131+
}
132+
133+
/**
134+
* An error indicating a network timeout occurred
135+
*
136+
* @param {Error|string|object} message The error message
137+
* @property {string} message The error message
138+
* @property {object} [options.beforeHandshake] Indicates the timeout happened before a connection handshake completed
139+
* @extends MongoError
140+
*/
141+
class MongoNetworkTimeoutError extends MongoNetworkError {
142+
constructor(message, options) {
143+
super(message, options);
144+
this.name = 'MongoNetworkTimeoutError';
121145
}
122146
}
123147

@@ -363,6 +387,7 @@ module.exports = {
363387
GET_MORE_RESUMABLE_CODES,
364388
MongoError,
365389
MongoNetworkError,
390+
MongoNetworkTimeoutError,
366391
MongoParseError,
367392
MongoTimeoutError,
368393
MongoServerSelectionError,
@@ -372,5 +397,6 @@ module.exports = {
372397
isNodeShuttingDownError,
373398
isNetworkTimeoutError,
374399
isRetryableWriteError,
375-
isResumableError
400+
isResumableError,
401+
isNetworkErrorBeforeHandshake
376402
};

lib/operations/connect.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ const validOptionNames = [
113113
'minHeartbeatFrequencyMS',
114114
'heartbeatFrequencyMS',
115115
'waitQueueTimeoutMS',
116-
'directConnection'
116+
'directConnection',
117+
'appName'
117118
];
118119

119120
const ignoreOptionNames = ['native_parser'];

0 commit comments

Comments
 (0)