Skip to content

Commit c28608b

Browse files
W-A-Jamesnbbeeken
authored andcommitted
feat(NODE-6446): deprecate legacy timeout options (#4279)
Co-authored-by: Neal Beeken <[email protected]>
1 parent 55e08e7 commit c28608b

16 files changed

+140
-52
lines changed

src/connection_string.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1092,6 +1092,7 @@ export const OPTIONS = {
10921092
type: 'string'
10931093
},
10941094
socketTimeoutMS: {
1095+
deprecated: 'Please use timeoutMS instead',
10951096
default: 0,
10961097
type: 'uint'
10971098
},
@@ -1162,6 +1163,7 @@ export const OPTIONS = {
11621163
}
11631164
},
11641165
waitQueueTimeoutMS: {
1166+
deprecated: 'Please use timeoutMS instead',
11651167
default: 0,
11661168
type: 'uint'
11671169
},

src/cursor/abstract_cursor.ts

+2
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ export interface AbstractCursorOptions extends BSONSerializeOptions {
8484
/**
8585
* When applicable `maxTimeMS` controls the amount of time the initial command
8686
* that constructs a cursor should take. (ex. find, aggregate, listCollections)
87+
* @deprecated Will be removed in the next major version. Please use timeoutMS instead.
8788
*/
8889
maxTimeMS?: number;
8990
/**
@@ -721,6 +722,7 @@ export abstract class AbstractCursor<
721722
* Set a maxTimeMS on the cursor query, allowing for hard timeout limits on queries (Only supported on MongoDB 2.6 or higher)
722723
*
723724
* @param value - Number of milliseconds to wait before aborting the query.
725+
* @deprecated Will be removed in the next major version. Please use the timeoutMS option instead.
724726
*/
725727
maxTimeMS(value: number): this {
726728
this.throwIfInitialized();

src/cursor/aggregation_cursor.ts

+8-6
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,14 @@ export class AggregationCursor<TSchema = any> extends ExplainableCursor<TSchema>
7575
...this.cursorOptions,
7676
session
7777
};
78-
try {
79-
validateExplainTimeoutOptions(options, Explain.fromOptions(options));
80-
} catch {
81-
throw new MongoAPIError(
82-
'timeoutMS cannot be used with explain when explain is specified in aggregateOptions'
83-
);
78+
if (options.explain) {
79+
try {
80+
validateExplainTimeoutOptions(options, Explain.fromOptions(options));
81+
} catch {
82+
throw new MongoAPIError(
83+
'timeoutMS cannot be used with explain when explain is specified in aggregateOptions'
84+
);
85+
}
8486
}
8587

8688
const aggregateOperation = new AggregateOperation(this.namespace, this.pipeline, options);

src/cursor/find_cursor.ts

+8-6
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,14 @@ export class FindCursor<TSchema = any> extends ExplainableCursor<TSchema> {
7575
session
7676
};
7777

78-
try {
79-
validateExplainTimeoutOptions(options, Explain.fromOptions(options));
80-
} catch {
81-
throw new MongoAPIError(
82-
'timeoutMS cannot be used with explain when explain is specified in findOptions'
83-
);
78+
if (options.explain) {
79+
try {
80+
validateExplainTimeoutOptions(options, Explain.fromOptions(options));
81+
} catch {
82+
throw new MongoAPIError(
83+
'timeoutMS cannot be used with explain when explain is specified in findOptions'
84+
);
85+
}
8486
}
8587

8688
const findOperation = new FindOperation(this.namespace, this.cursorFilter, options);

src/cursor/run_command_cursor.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export class RunCommandCursor extends AbstractCursor {
4848
/**
4949
* Controls the `getMore.maxTimeMS` field. Only valid when cursor is tailable await
5050
* @param maxTimeMS - the number of milliseconds to wait for new data
51+
* @deprecated Will be removed in the next major version. Please use timeoutMS instead.
5152
*/
5253
public setMaxTimeMS(maxTimeMS: number): this {
5354
this.getMoreOptions.maxAwaitTimeMS = maxTimeMS;
@@ -56,7 +57,7 @@ export class RunCommandCursor extends AbstractCursor {
5657

5758
/**
5859
* Controls the `getMore.batchSize` field
59-
* @param maxTimeMS - the number documents to return in the `nextBatch`
60+
* @param batchSize - the number documents to return in the `nextBatch`
6061
*/
6162
public setBatchSize(batchSize: number): this {
6263
this.getMoreOptions.batchSize = batchSize;
@@ -82,7 +83,10 @@ export class RunCommandCursor extends AbstractCursor {
8283
);
8384
}
8485

85-
/** Unsupported for RunCommandCursor: maxTimeMS must be configured directly on command document */
86+
/**
87+
* Unsupported for RunCommandCursor: maxTimeMS must be configured directly on command document
88+
* @deprecated Will be removed in the next major version.
89+
*/
8690
public override maxTimeMS(_: number): never {
8791
throw new MongoAPIError(
8892
'maxTimeMS must be configured on the command document directly, to configure getMore.maxTimeMS use cursor.setMaxTimeMS()'

src/mongo_client.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,10 @@ export interface MongoClientOptions extends BSONSerializeOptions, SupportedNodeC
152152
tlsInsecure?: boolean;
153153
/** The time in milliseconds to attempt a connection before timing out. */
154154
connectTimeoutMS?: number;
155-
/** The time in milliseconds to attempt a send or receive on a socket before the attempt times out. */
155+
/**
156+
* The time in milliseconds to attempt a send or receive on a socket before the attempt times out.
157+
* @deprecated Will be removed in the next major version. Please use timeoutMS instead
158+
*/
156159
socketTimeoutMS?: number;
157160
/** An array or comma-delimited string of compressors to enable network compression for communication between this client and a mongod/mongos instance. */
158161
compressors?: CompressorName[] | string;
@@ -176,7 +179,10 @@ export interface MongoClientOptions extends BSONSerializeOptions, SupportedNodeC
176179
maxConnecting?: number;
177180
/** The maximum number of milliseconds that a connection can remain idle in the pool before being removed and closed. */
178181
maxIdleTimeMS?: number;
179-
/** The maximum time in milliseconds that a thread can wait for a connection to become available. */
182+
/**
183+
* The maximum time in milliseconds that a thread can wait for a connection to become available.
184+
* @deprecated Will be removed in the next major version. Please use timeoutMS instead
185+
*/
180186
waitQueueTimeoutMS?: number;
181187
/** Specify a read concern for the collection (only MongoDB 3.2 or higher supported) */
182188
readConcern?: ReadConcernLike;

src/operations/aggregate.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ export interface AggregateOptions extends Omit<CommandOperationOptions, 'explain
2626
bypassDocumentValidation?: boolean;
2727
/** Return the query as cursor, on 2.6 \> it returns as a real cursor on pre 2.6 it returns as an emulated cursor. */
2828
cursor?: Document;
29-
/** specifies a cumulative time limit in milliseconds for processing operations on the cursor. MongoDB interrupts the operation at the earliest following interrupt point. */
29+
/**
30+
* Specifies a cumulative time limit in milliseconds for processing operations on the cursor. MongoDB interrupts the operation at the earliest following interrupt point.
31+
* @deprecated Will be removed in the next major version. Please use timeoutMS instead.
32+
*/
3033
maxTimeMS?: number;
3134
/** The maximum amount of time for the server to wait on new documents to satisfy a tailable cursor query. */
3235
maxAwaitTimeMS?: number;

src/operations/command.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ export interface CommandOperationOptions
4040
readConcern?: ReadConcernLike;
4141
/** Collation */
4242
collation?: CollationOptions;
43+
/**
44+
* maxTimeMS is a server-side time limit in milliseconds for processing an operation.
45+
* @deprecated Will be removed in the next major version. Please use timeoutMS instead.
46+
*/
4347
maxTimeMS?: number;
4448
/**
4549
* Comment to apply to the operation.
@@ -97,7 +101,7 @@ export abstract class CommandOperation<T> extends AbstractOperation<T> {
97101

98102
if (this.hasAspect(Aspect.EXPLAINABLE)) {
99103
this.explain = Explain.fromOptions(options);
100-
validateExplainTimeoutOptions(this.options, this.explain);
104+
if (this.explain) validateExplainTimeoutOptions(this.options, this.explain);
101105
} else if (options?.explain != null) {
102106
throw new MongoInvalidArgumentError(`Option "explain" is not supported on this command`);
103107
}

src/operations/count.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ export interface CountOptions extends CommandOperationOptions {
1313
skip?: number;
1414
/** The maximum amounts to count before aborting. */
1515
limit?: number;
16-
/** Number of milliseconds to wait before aborting the query. */
16+
/**
17+
* Number of milliseconds to wait before aborting the query.
18+
* @deprecated Will be removed in the next major version. Please use timeoutMS instead.
19+
*/
1720
maxTimeMS?: number;
1821
/** An index name hint for the query. */
1922
hint?: string | Document;

src/operations/estimated_document_count.ts

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export interface EstimatedDocumentCountOptions extends CommandOperationOptions {
1212
* The maximum amount of time to allow the operation to run.
1313
*
1414
* This option is sent only if the caller explicitly provides a value. The default is to not send a value.
15+
* @deprecated Will be removed in the next major version. Please use timeoutMS instead.
1516
*/
1617
maxTimeMS?: number;
1718
}

src/sessions.ts

+35-24
Original file line numberDiff line numberDiff line change
@@ -487,13 +487,31 @@ export class ClientSession
487487
maxTimeMS?: number;
488488
} = { commitTransaction: 1 };
489489

490+
const timeoutMS =
491+
typeof options?.timeoutMS === 'number'
492+
? options.timeoutMS
493+
: typeof this.timeoutMS === 'number'
494+
? this.timeoutMS
495+
: null;
496+
490497
const wc = this.transaction.options.writeConcern ?? this.clientOptions?.writeConcern;
491498
if (wc != null) {
492-
WriteConcern.apply(command, { wtimeoutMS: 10000, w: 'majority', ...wc });
499+
if (timeoutMS == null && this.timeoutContext == null) {
500+
WriteConcern.apply(command, { wtimeoutMS: 10000, w: 'majority', ...wc });
501+
} else {
502+
const wcKeys = Object.keys(wc);
503+
if (wcKeys.length > 2 || (!wcKeys.includes('wtimeoutMS') && !wcKeys.includes('wTimeoutMS')))
504+
// if the write concern was specified with wTimeoutMS, then we set both wtimeoutMS and wTimeoutMS, guaranteeing at least two keys, so if we have more than two keys, then we can automatically assume that we should add the write concern to the command. If it has 2 or fewer keys, we need to check that those keys aren't the wtimeoutMS or wTimeoutMS options before we add the write concern to the command
505+
WriteConcern.apply(command, { ...wc, wtimeoutMS: undefined });
506+
}
493507
}
494508

495509
if (this.transaction.state === TxnState.TRANSACTION_COMMITTED || this.commitAttempted) {
496-
WriteConcern.apply(command, { wtimeoutMS: 10000, ...wc, w: 'majority' });
510+
if (timeoutMS == null && this.timeoutContext == null) {
511+
WriteConcern.apply(command, { wtimeoutMS: 10000, ...wc, w: 'majority' });
512+
} else {
513+
WriteConcern.apply(command, { w: 'majority', ...wc, wtimeoutMS: undefined });
514+
}
497515
}
498516

499517
if (typeof this.transaction.options.maxTimeMS === 'number') {
@@ -510,13 +528,6 @@ export class ClientSession
510528
bypassPinningCheck: true
511529
});
512530

513-
const timeoutMS =
514-
typeof options?.timeoutMS === 'number'
515-
? options.timeoutMS
516-
: typeof this.timeoutMS === 'number'
517-
? this.timeoutMS
518-
: null;
519-
520531
const timeoutContext =
521532
this.timeoutContext ??
522533
(typeof timeoutMS === 'number'
@@ -616,21 +627,6 @@ export class ClientSession
616627
recoveryToken?: Document;
617628
} = { abortTransaction: 1 };
618629

619-
const wc = this.transaction.options.writeConcern ?? this.clientOptions?.writeConcern;
620-
if (wc != null) {
621-
WriteConcern.apply(command, { wtimeoutMS: 10000, w: 'majority', ...wc });
622-
}
623-
624-
if (this.transaction.recoveryToken) {
625-
command.recoveryToken = this.transaction.recoveryToken;
626-
}
627-
628-
const operation = new RunAdminCommandOperation(command, {
629-
session: this,
630-
readPreference: ReadPreference.primary,
631-
bypassPinningCheck: true
632-
});
633-
634630
const timeoutMS =
635631
typeof options?.timeoutMS === 'number'
636632
? options.timeoutMS
@@ -649,6 +645,21 @@ export class ClientSession
649645
})
650646
: null;
651647

648+
const wc = this.transaction.options.writeConcern ?? this.clientOptions?.writeConcern;
649+
if (wc != null && timeoutMS == null) {
650+
WriteConcern.apply(command, { wtimeoutMS: 10000, w: 'majority', ...wc });
651+
}
652+
653+
if (this.transaction.recoveryToken) {
654+
command.recoveryToken = this.transaction.recoveryToken;
655+
}
656+
657+
const operation = new RunAdminCommandOperation(command, {
658+
session: this,
659+
readPreference: ReadPreference.primary,
660+
bypassPinningCheck: true
661+
});
662+
652663
try {
653664
await executeOperation(this.client, operation, timeoutContext);
654665
this.unpin();

src/utils.ts

+12-3
Original file line numberDiff line numberDiff line change
@@ -516,20 +516,31 @@ export function resolveOptions<T extends CommandOperationOptions>(
516516
): T {
517517
const result: T = Object.assign({}, options, resolveBSONOptions(options, parent));
518518

519+
const timeoutMS = options?.timeoutMS ?? parent?.timeoutMS;
519520
// Users cannot pass a readConcern/writeConcern to operations in a transaction
520521
const session = options?.session;
522+
521523
if (!session?.inTransaction()) {
522524
const readConcern = ReadConcern.fromOptions(options) ?? parent?.readConcern;
523525
if (readConcern) {
524526
result.readConcern = readConcern;
525527
}
526528

527-
const writeConcern = WriteConcern.fromOptions(options) ?? parent?.writeConcern;
529+
let writeConcern = WriteConcern.fromOptions(options) ?? parent?.writeConcern;
528530
if (writeConcern) {
531+
if (timeoutMS != null) {
532+
writeConcern = WriteConcern.fromOptions({
533+
...writeConcern,
534+
wtimeout: undefined,
535+
wtimeoutMS: undefined
536+
});
537+
}
529538
result.writeConcern = writeConcern;
530539
}
531540
}
532541

542+
result.timeoutMS = timeoutMS;
543+
533544
const readPreference = ReadPreference.fromOptions(options) ?? parent?.readPreference;
534545
if (readPreference) {
535546
result.readPreference = readPreference;
@@ -542,8 +553,6 @@ export function resolveOptions<T extends CommandOperationOptions>(
542553
);
543554
}
544555

545-
result.timeoutMS = options?.timeoutMS ?? parent?.timeoutMS;
546-
547556
return result;
548557
}
549558

src/write_concern.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ export interface WriteConcernOptions {
1515
export interface WriteConcernSettings {
1616
/** The write concern */
1717
w?: W;
18-
/** The write concern timeout */
18+
/** The write concern timeout
19+
* @deprecated Will be removed in the next major version. Please use timeoutMS */
1920
wtimeoutMS?: number;
2021
/** The journal write concern */
2122
journal?: boolean;
@@ -28,7 +29,8 @@ export interface WriteConcernSettings {
2829
j?: boolean;
2930
/**
3031
* The write concern timeout.
31-
* @deprecated Will be removed in the next major version. Please use the wtimeoutMS option.
32+
* @deprecated
33+
* Will be removed in the next major version. Please use the wtimeoutMS option.
3234
*/
3335
wtimeout?: number;
3436
/**
@@ -65,7 +67,10 @@ export class WriteConcern {
6567
readonly w?: W;
6668
/** Request acknowledgment that the write operation has been written to the on-disk journal */
6769
readonly journal?: boolean;
68-
/** Specify a time limit to prevent write operations from blocking indefinitely */
70+
/**
71+
* Specify a time limit to prevent write operations from blocking indefinitely.
72+
* @deprecated Will be removed in the next major version. Please use timeoutMS
73+
*/
6974
readonly wtimeoutMS?: number;
7075
/**
7176
* Specify a time limit to prevent write operations from blocking indefinitely.

test/integration/client-side-operations-timeout/client_side_operations_timeout.spec.test.ts

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { runUnifiedSuite } from '../../tools/unified-spec-runner/runner';
77
const skippedSpecs = {
88
'change-streams': 'TODO(NODE-6035)',
99
'convenient-transactions': 'TODO(NODE-5687)',
10-
'deprecated-options': 'TODO(NODE-5689)',
1110
'tailable-awaitData': 'TODO(NODE-6035)',
1211
'tailable-non-awaitData': 'TODO(NODE-6035)'
1312
};

test/types/mongodb.test-d.ts

+30
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,39 @@ declare const options: MongoDBDriver.MongoClientOptions;
2020
expectDeprecated(options.w);
2121
expectDeprecated(options.journal);
2222
expectDeprecated(options.wtimeoutMS);
23+
expectDeprecated(options.socketTimeoutMS);
24+
expectDeprecated(options.waitQueueTimeoutMS);
2325
expectNotDeprecated(options.writeConcern);
26+
expectNotDeprecated(options.serverSelectionTimeoutMS);
27+
expectNotDeprecated(options.connectTimeoutMS);
28+
2429
expectType<WriteConcernSettings | WriteConcern | undefined>(options.writeConcern);
2530

31+
declare const estimatedDocumentCountOptions: MongoDBDriver.EstimatedDocumentCountOptions;
32+
expectDeprecated(estimatedDocumentCountOptions.maxTimeMS);
33+
34+
declare const countOptions: MongoDBDriver.CountOptions;
35+
expectDeprecated(countOptions.maxTimeMS);
36+
37+
declare const commandOptions: MongoDBDriver.CommandOperationOptions;
38+
expectDeprecated(commandOptions.maxTimeMS);
39+
40+
declare const aggregateOptions: MongoDBDriver.AggregateOptions;
41+
expectDeprecated(aggregateOptions.maxTimeMS);
42+
43+
declare const runCommandCursor: MongoDBDriver.RunCommandCursor;
44+
expectDeprecated(runCommandCursor.setMaxTimeMS);
45+
expectDeprecated(runCommandCursor.maxTimeMS);
46+
47+
declare const cursorOptions: MongoDBDriver.AbstractCursorOptions;
48+
expectDeprecated(cursorOptions.maxTimeMS);
49+
50+
declare const abstractCursor: MongoDBDriver.AbstractCursor;
51+
expectDeprecated(abstractCursor.maxTimeMS);
52+
53+
declare const txnOptions: MongoDBDriver.TransactionOptions;
54+
expectDeprecated(txnOptions.maxCommitTimeMS);
55+
2656
interface TSchema extends Document {
2757
name: string;
2858
}

0 commit comments

Comments
 (0)