Skip to content

Commit 20564f7

Browse files
refactor(NODE-6524): consolidate socket timeout calculation (#4320)
1 parent 247284e commit 20564f7

File tree

4 files changed

+37
-28
lines changed

4 files changed

+37
-28
lines changed

src/cmap/connection.ts

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -427,10 +427,7 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
427427
...options
428428
};
429429

430-
if (!options.omitMaxTimeMS) {
431-
const maxTimeMS = options.timeoutContext?.maxTimeMS;
432-
if (maxTimeMS && maxTimeMS > 0 && Number.isFinite(maxTimeMS)) cmd.maxTimeMS = maxTimeMS;
433-
}
430+
options.timeoutContext?.addMaxTimeMSToCommand(cmd, options);
434431

435432
const message = this.supportsOpMsg
436433
? new OpMsgRequest(db, cmd, commandOptions)
@@ -446,13 +443,11 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
446443
): AsyncGenerator<MongoDBResponse> {
447444
this.throwIfAborted();
448445

449-
if (options.timeoutContext?.csotEnabled()) {
450-
this.socket.setTimeout(0);
451-
} else if (typeof options.socketTimeoutMS === 'number') {
452-
this.socket.setTimeout(options.socketTimeoutMS);
453-
} else if (this.socketTimeoutMS !== 0) {
454-
this.socket.setTimeout(this.socketTimeoutMS);
455-
}
446+
const timeout =
447+
options.socketTimeoutMS ??
448+
options?.timeoutContext?.getSocketTimeoutMS() ??
449+
this.socketTimeoutMS;
450+
this.socket.setTimeout(timeout);
456451

457452
try {
458453
await this.writeCommand(message, {
@@ -487,11 +482,7 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
487482
yield document;
488483
this.throwIfAborted();
489484

490-
if (typeof options.socketTimeoutMS === 'number') {
491-
this.socket.setTimeout(options.socketTimeoutMS);
492-
} else if (this.socketTimeoutMS !== 0) {
493-
this.socket.setTimeout(this.socketTimeoutMS);
494-
}
485+
this.socket.setTimeout(timeout);
495486
}
496487
} finally {
497488
this.socket.setTimeout(0);

src/cmap/connection_pool.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
402402
}
403403
throw error;
404404
} finally {
405-
if (options.timeoutContext.clearConnectionCheckoutTimeout) timeout?.clear();
405+
timeout?.clear();
406406
}
407407
}
408408

src/cursor/abstract_cursor.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,9 +1169,6 @@ export class CursorTimeoutContext extends TimeoutContext {
11691169
override get clearServerSelectionTimeout(): boolean {
11701170
return this.timeoutContext.clearServerSelectionTimeout;
11711171
}
1172-
override get clearConnectionCheckoutTimeout(): boolean {
1173-
return this.timeoutContext.clearConnectionCheckoutTimeout;
1174-
}
11751172
override get timeoutForSocketWrite(): Timeout | null {
11761173
return this.timeoutContext.timeoutForSocketWrite;
11771174
}
@@ -1190,12 +1187,16 @@ export class CursorTimeoutContext extends TimeoutContext {
11901187
override get maxTimeMS(): number | null {
11911188
return this.timeoutContext.maxTimeMS;
11921189
}
1193-
11941190
get timeoutMS(): number | null {
11951191
return this.timeoutContext.csotEnabled() ? this.timeoutContext.timeoutMS : null;
11961192
}
1197-
11981193
override refreshed(): CursorTimeoutContext {
11991194
return new CursorTimeoutContext(this.timeoutContext.refreshed(), this.owner);
12001195
}
1196+
override addMaxTimeMSToCommand(command: Document, options: { omitMaxTimeMS?: boolean }): void {
1197+
this.timeoutContext.addMaxTimeMSToCommand(command, options);
1198+
}
1199+
override getSocketTimeoutMS(): number | undefined {
1200+
return this.timeoutContext.getSocketTimeoutMS();
1201+
}
12011202
}

src/timeout.ts

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { clearTimeout, setTimeout } from 'timers';
22

3+
import { type Document } from './bson';
34
import { MongoInvalidArgumentError, MongoOperationTimeoutError, MongoRuntimeError } from './error';
45
import { type ClientSession } from './sessions';
56
import { csotMin, noop } from './utils';
@@ -171,8 +172,6 @@ export abstract class TimeoutContext {
171172

172173
abstract get clearServerSelectionTimeout(): boolean;
173174

174-
abstract get clearConnectionCheckoutTimeout(): boolean;
175-
176175
abstract get timeoutForSocketWrite(): Timeout | null;
177176

178177
abstract get timeoutForSocketRead(): Timeout | null;
@@ -185,6 +184,10 @@ export abstract class TimeoutContext {
185184

186185
/** Returns a new instance of the TimeoutContext, with all timeouts refreshed and restarted. */
187186
abstract refreshed(): TimeoutContext;
187+
188+
abstract addMaxTimeMSToCommand(command: Document, options: { omitMaxTimeMS?: boolean }): void;
189+
190+
abstract getSocketTimeoutMS(): number | undefined;
188191
}
189192

190193
/** @internal */
@@ -193,7 +196,6 @@ export class CSOTTimeoutContext extends TimeoutContext {
193196
serverSelectionTimeoutMS: number;
194197
socketTimeoutMS?: number;
195198

196-
clearConnectionCheckoutTimeout: boolean;
197199
clearServerSelectionTimeout: boolean;
198200

199201
private _serverSelectionTimeout?: Timeout | null;
@@ -212,7 +214,6 @@ export class CSOTTimeoutContext extends TimeoutContext {
212214
this.socketTimeoutMS = options.socketTimeoutMS;
213215

214216
this.clearServerSelectionTimeout = false;
215-
this.clearConnectionCheckoutTimeout = true;
216217
}
217218

218219
get maxTimeMS(): number {
@@ -325,19 +326,27 @@ export class CSOTTimeoutContext extends TimeoutContext {
325326
override refreshed(): CSOTTimeoutContext {
326327
return new CSOTTimeoutContext(this);
327328
}
329+
330+
override addMaxTimeMSToCommand(command: Document, options: { omitMaxTimeMS?: boolean }): void {
331+
if (options.omitMaxTimeMS) return;
332+
const maxTimeMS = this.remainingTimeMS - this.minRoundTripTime;
333+
if (maxTimeMS > 0 && Number.isFinite(maxTimeMS)) command.maxTimeMS = maxTimeMS;
334+
}
335+
336+
override getSocketTimeoutMS(): number | undefined {
337+
return 0;
338+
}
328339
}
329340

330341
/** @internal */
331342
export class LegacyTimeoutContext extends TimeoutContext {
332343
options: LegacyTimeoutContextOptions;
333344
clearServerSelectionTimeout: boolean;
334-
clearConnectionCheckoutTimeout: boolean;
335345

336346
constructor(options: LegacyTimeoutContextOptions) {
337347
super();
338348
this.options = options;
339349
this.clearServerSelectionTimeout = true;
340-
this.clearConnectionCheckoutTimeout = true;
341350
}
342351

343352
csotEnabled(): this is CSOTTimeoutContext {
@@ -379,4 +388,12 @@ export class LegacyTimeoutContext extends TimeoutContext {
379388
override refreshed(): LegacyTimeoutContext {
380389
return new LegacyTimeoutContext(this.options);
381390
}
391+
392+
override addMaxTimeMSToCommand(_command: Document, _options: { omitMaxTimeMS?: boolean }): void {
393+
// No max timeMS is added to commands in legacy timeout mode.
394+
}
395+
396+
override getSocketTimeoutMS(): number | undefined {
397+
return this.options.socketTimeoutMS;
398+
}
382399
}

0 commit comments

Comments
 (0)