Skip to content

Commit ebbfb8a

Browse files
authored
fix(NODE-5749): RTTPinger always sends legacy hello (#3921)
1 parent ae4c94a commit ebbfb8a

File tree

4 files changed

+217
-44
lines changed

4 files changed

+217
-44
lines changed

src/sdam/monitor.ts

+26-26
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ const kConnection = Symbol('connection');
2727
/** @internal */
2828
const kCancellationToken = Symbol('cancellationToken');
2929
/** @internal */
30-
const kRTTPinger = Symbol('rttPinger');
31-
/** @internal */
3230
const kRoundTripTime = Symbol('roundTripTime');
3331

3432
const STATE_IDLE = 'idle';
@@ -100,7 +98,7 @@ export class Monitor extends TypedEventEmitter<MonitorEvents> {
10098
[kCancellationToken]: CancellationToken;
10199
/** @internal */
102100
[kMonitorId]?: MonitorInterval;
103-
[kRTTPinger]?: RTTPinger;
101+
rttPinger?: RTTPinger;
104102

105103
get connection(): Connection | undefined {
106104
return this[kConnection];
@@ -219,8 +217,8 @@ function resetMonitorState(monitor: Monitor) {
219217
monitor[kMonitorId]?.stop();
220218
monitor[kMonitorId] = undefined;
221219

222-
monitor[kRTTPinger]?.close();
223-
monitor[kRTTPinger] = undefined;
220+
monitor.rttPinger?.close();
221+
monitor.rttPinger = undefined;
224222

225223
monitor[kCancellationToken].emit('cancel');
226224

@@ -294,8 +292,8 @@ function checkServer(monitor: Monitor, callback: Callback<Document | null>) {
294292
}
295293
: { socketTimeoutMS: connectTimeoutMS };
296294

297-
if (isAwaitable && monitor[kRTTPinger] == null) {
298-
monitor[kRTTPinger] = new RTTPinger(
295+
if (isAwaitable && monitor.rttPinger == null) {
296+
monitor.rttPinger = new RTTPinger(
299297
monitor[kCancellationToken],
300298
Object.assign(
301299
{ heartbeatFrequencyMS: monitor.options.heartbeatFrequencyMS },
@@ -314,9 +312,10 @@ function checkServer(monitor: Monitor, callback: Callback<Document | null>) {
314312
hello.isWritablePrimary = hello[LEGACY_HELLO_COMMAND];
315313
}
316314

317-
const rttPinger = monitor[kRTTPinger];
318315
const duration =
319-
isAwaitable && rttPinger ? rttPinger.roundTripTime : calculateDurationInMs(start);
316+
isAwaitable && monitor.rttPinger
317+
? monitor.rttPinger.roundTripTime
318+
: calculateDurationInMs(start);
320319

321320
monitor.emit(
322321
Server.SERVER_HEARTBEAT_SUCCEEDED,
@@ -332,8 +331,8 @@ function checkServer(monitor: Monitor, callback: Callback<Document | null>) {
332331
);
333332
start = now();
334333
} else {
335-
monitor[kRTTPinger]?.close();
336-
monitor[kRTTPinger] = undefined;
334+
monitor.rttPinger?.close();
335+
monitor.rttPinger = undefined;
337336

338337
callback(undefined, hello);
339338
}
@@ -430,8 +429,7 @@ export interface RTTPingerOptions extends ConnectionOptions {
430429

431430
/** @internal */
432431
export class RTTPinger {
433-
/** @internal */
434-
[kConnection]?: Connection;
432+
connection?: Connection;
435433
/** @internal */
436434
[kCancellationToken]: CancellationToken;
437435
/** @internal */
@@ -441,7 +439,7 @@ export class RTTPinger {
441439
closed: boolean;
442440

443441
constructor(cancellationToken: CancellationToken, options: RTTPingerOptions) {
444-
this[kConnection] = undefined;
442+
this.connection = undefined;
445443
this[kCancellationToken] = cancellationToken;
446444
this[kRoundTripTime] = 0;
447445
this.closed = false;
@@ -458,8 +456,8 @@ export class RTTPinger {
458456
this.closed = true;
459457
clearTimeout(this[kMonitorId]);
460458

461-
this[kConnection]?.destroy({ force: true });
462-
this[kConnection] = undefined;
459+
this.connection?.destroy({ force: true });
460+
this.connection = undefined;
463461
}
464462
}
465463

@@ -478,8 +476,8 @@ function measureRoundTripTime(rttPinger: RTTPinger, options: RTTPingerOptions) {
478476
return;
479477
}
480478

481-
if (rttPinger[kConnection] == null) {
482-
rttPinger[kConnection] = conn;
479+
if (rttPinger.connection == null) {
480+
rttPinger.connection = conn;
483481
}
484482

485483
rttPinger[kRoundTripTime] = calculateDurationInMs(start);
@@ -489,11 +487,11 @@ function measureRoundTripTime(rttPinger: RTTPinger, options: RTTPingerOptions) {
489487
);
490488
}
491489

492-
const connection = rttPinger[kConnection];
490+
const connection = rttPinger.connection;
493491
if (connection == null) {
494492
connect(options, (err, conn) => {
495493
if (err) {
496-
rttPinger[kConnection] = undefined;
494+
rttPinger.connection = undefined;
497495
rttPinger[kRoundTripTime] = 0;
498496
return;
499497
}
@@ -504,15 +502,17 @@ function measureRoundTripTime(rttPinger: RTTPinger, options: RTTPingerOptions) {
504502
return;
505503
}
506504

507-
connection.command(ns('admin.$cmd'), { [LEGACY_HELLO_COMMAND]: 1 }, undefined, err => {
508-
if (err) {
509-
rttPinger[kConnection] = undefined;
505+
const commandName =
506+
connection.serverApi?.version || connection.helloOk ? 'hello' : LEGACY_HELLO_COMMAND;
507+
connection.commandAsync(ns('admin.$cmd'), { [commandName]: 1 }, undefined).then(
508+
() => measureAndReschedule(),
509+
() => {
510+
rttPinger.connection?.destroy({ force: true });
511+
rttPinger.connection = undefined;
510512
rttPinger[kRoundTripTime] = 0;
511513
return;
512514
}
513-
514-
measureAndReschedule();
515-
});
515+
);
516516
}
517517

518518
/**

src/sdam/server.ts

+10-15
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,6 @@ const stateTransition = makeStateMachine({
7474
[STATE_CLOSING]: [STATE_CLOSING, STATE_CLOSED]
7575
});
7676

77-
/** @internal */
78-
const kMonitor = Symbol('monitor');
79-
8077
/** @internal */
8178
export type ServerOptions = Omit<ConnectionPoolOptions, 'id' | 'generation' | 'hostAddress'> &
8279
MonitorOptions;
@@ -119,7 +116,7 @@ export class Server extends TypedEventEmitter<ServerEvents> {
119116
serverApi?: ServerApi;
120117
hello?: Document;
121118
commandAsync: (ns: MongoDBNamespace, cmd: Document, options: CommandOptions) => Promise<Document>;
122-
[kMonitor]: Monitor | null;
119+
monitor: Monitor | null;
123120

124121
/** @event */
125122
static readonly SERVER_HEARTBEAT_STARTED = SERVER_HEARTBEAT_STARTED;
@@ -175,22 +172,20 @@ export class Server extends TypedEventEmitter<ServerEvents> {
175172
});
176173

177174
if (this.loadBalanced) {
178-
this[kMonitor] = null;
175+
this.monitor = null;
179176
// monitoring is disabled in load balancing mode
180177
return;
181178
}
182179

183180
// create the monitor
184-
// TODO(NODE-4144): Remove new variable for type narrowing
185-
const monitor = new Monitor(this, this.s.options);
186-
this[kMonitor] = monitor;
181+
this.monitor = new Monitor(this, this.s.options);
187182

188183
for (const event of HEARTBEAT_EVENTS) {
189-
monitor.on(event, (e: any) => this.emit(event, e));
184+
this.monitor.on(event, (e: any) => this.emit(event, e));
190185
}
191186

192-
monitor.on('resetServer', (error: MongoError) => markServerUnknown(this, error));
193-
monitor.on(Server.SERVER_HEARTBEAT_SUCCEEDED, (event: ServerHeartbeatSucceededEvent) => {
187+
this.monitor.on('resetServer', (error: MongoError) => markServerUnknown(this, error));
188+
this.monitor.on(Server.SERVER_HEARTBEAT_SUCCEEDED, (event: ServerHeartbeatSucceededEvent) => {
194189
this.emit(
195190
Server.DESCRIPTION_RECEIVED,
196191
new ServerDescription(this.description.hostAddress, event.reply, {
@@ -246,7 +241,7 @@ export class Server extends TypedEventEmitter<ServerEvents> {
246241
// a load balancer. It never transitions out of this state and
247242
// has no monitor.
248243
if (!this.loadBalanced) {
249-
this[kMonitor]?.connect();
244+
this.monitor?.connect();
250245
} else {
251246
stateTransition(this, STATE_CONNECTED);
252247
this.emit(Server.CONNECT, this);
@@ -272,7 +267,7 @@ export class Server extends TypedEventEmitter<ServerEvents> {
272267
stateTransition(this, STATE_CLOSING);
273268

274269
if (!this.loadBalanced) {
275-
this[kMonitor]?.close();
270+
this.monitor?.close();
276271
}
277272

278273
this.pool.close(options, err => {
@@ -290,7 +285,7 @@ export class Server extends TypedEventEmitter<ServerEvents> {
290285
*/
291286
requestCheck(): void {
292287
if (!this.loadBalanced) {
293-
this[kMonitor]?.requestCheck();
288+
this.monitor?.requestCheck();
294289
}
295290
}
296291

@@ -465,7 +460,7 @@ function markServerUnknown(server: Server, error?: MongoServerError) {
465460
}
466461

467462
if (error instanceof MongoNetworkError && !(error instanceof MongoNetworkTimeoutError)) {
468-
server[kMonitor]?.reset();
463+
server.monitor?.reset();
469464
}
470465

471466
server.emit(

0 commit comments

Comments
 (0)