Skip to content

Commit 22d8c17

Browse files
W-A-Jamesnbbeekenaditi-khare-mongoDB
committed
docs(NODE-6456): document CSOT pt 1 (#4292)
Co-authored-by: Neal Beeken <[email protected]> Co-authored-by: Aditi Khare <[email protected]>
1 parent 3932a03 commit 22d8c17

File tree

14 files changed

+154
-57
lines changed

14 files changed

+154
-57
lines changed

src/collection.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,10 @@ export interface CollectionOptions extends BSONSerializeOptions, WriteConcernOpt
115115
readConcern?: ReadConcernLike;
116116
/** The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). */
117117
readPreference?: ReadPreferenceLike;
118-
/** @internal TODO(NODE-5688): make this public */
118+
/**
119+
* @experimental
120+
* Specifies the time an operation will run until it throws a timeout error
121+
*/
119122
timeoutMS?: number;
120123
}
121124

@@ -262,8 +265,7 @@ export class Collection<TSchema extends Document = Document> {
262265
this.s.collectionHint = normalizeHintField(v);
263266
}
264267

265-
/** @internal */
266-
get timeoutMS(): number | undefined {
268+
public get timeoutMS(): number | undefined {
267269
return this.s.options.timeoutMS;
268270
}
269271

src/cursor/abstract_cursor.ts

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,44 @@ export interface CursorStreamOptions {
6161
/** @public */
6262
export type CursorFlag = (typeof CURSOR_FLAGS)[number];
6363

64-
/** @public*/
64+
/**
65+
* @public
66+
* @experimental
67+
* Specifies how `timeoutMS` is applied to the cursor. Can be either `'cursorLifeTime'` or `'iteration'`
68+
* When set to `'iteration'`, the deadline specified by `timeoutMS` applies to each call of
69+
* `cursor.next()`.
70+
* When set to `'cursorLifetime'`, the deadline applies to the life of the entire cursor.
71+
*
72+
* Depending on the type of cursor being used, this option has different default values.
73+
* For non-tailable cursors, this value defaults to `'cursorLifetime'`
74+
* For tailable cursors, this value defaults to `'iteration'` since tailable cursors, by
75+
* definition can have an arbitrarily long lifetime.
76+
*
77+
* @example
78+
* ```ts
79+
* const cursor = collection.find({}, {timeoutMS: 100, timeoutMode: 'iteration'});
80+
* for await (const doc of cursor) {
81+
* // process doc
82+
* // This will throw a timeout error if any of the iterator's `next()` calls takes more than 100ms, but
83+
* // will continue to iterate successfully otherwise, regardless of the number of batches.
84+
* }
85+
* ```
86+
*
87+
* @example
88+
* ```ts
89+
* const cursor = collection.find({}, { timeoutMS: 1000, timeoutMode: 'cursorLifetime' });
90+
* const docs = await cursor.toArray(); // This entire line will throw a timeout error if all batches are not fetched and returned within 1000ms.
91+
* ```
92+
*/
6593
export const CursorTimeoutMode = Object.freeze({
6694
ITERATION: 'iteration',
6795
LIFETIME: 'cursorLifetime'
6896
} as const);
6997

70-
/** @public
71-
* TODO(NODE-5688): Document and release
72-
* */
98+
/**
99+
* @public
100+
* @experimental
101+
*/
73102
export type CursorTimeoutMode = (typeof CursorTimeoutMode)[keyof typeof CursorTimeoutMode];
74103

75104
/** @public */
@@ -116,9 +145,37 @@ export interface AbstractCursorOptions extends BSONSerializeOptions {
116145
*/
117146
awaitData?: boolean;
118147
noCursorTimeout?: boolean;
119-
/** @internal TODO(NODE-5688): make this public */
148+
/** Specifies the time an operation will run until it throws a timeout error. See {@link AbstractCursorOptions.timeoutMode} for more details on how this option applies to cursors. */
120149
timeoutMS?: number;
121-
/** @internal TODO(NODE-5688): make this public */
150+
/**
151+
* @public
152+
* @experimental
153+
* Specifies how `timeoutMS` is applied to the cursor. Can be either `'cursorLifeTime'` or `'iteration'`
154+
* When set to `'iteration'`, the deadline specified by `timeoutMS` applies to each call of
155+
* `cursor.next()`.
156+
* When set to `'cursorLifetime'`, the deadline applies to the life of the entire cursor.
157+
*
158+
* Depending on the type of cursor being used, this option has different default values.
159+
* For non-tailable cursors, this value defaults to `'cursorLifetime'`
160+
* For tailable cursors, this value defaults to `'iteration'` since tailable cursors, by
161+
* definition can have an arbitrarily long lifetime.
162+
*
163+
* @example
164+
* ```ts
165+
* const cursor = collection.find({}, {timeoutMS: 100, timeoutMode: 'iteration'});
166+
* for await (const doc of cursor) {
167+
* // process doc
168+
* // This will throw a timeout error if any of the iterator's `next()` calls takes more than 100ms, but
169+
* // will continue to iterate successfully otherwise, regardless of the number of batches.
170+
* }
171+
* ```
172+
*
173+
* @example
174+
* ```ts
175+
* const cursor = collection.find({}, { timeoutMS: 1000, timeoutMode: 'cursorLifetime' });
176+
* const docs = await cursor.toArray(); // This entire line will throw a timeout error if all batches are not fetched and returned within 1000ms.
177+
* ```
178+
*/
122179
timeoutMode?: CursorTimeoutMode;
123180

124181
/**

src/cursor/run_command_cursor.ts

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,42 @@ import {
1919
export type RunCursorCommandOptions = {
2020
readPreference?: ReadPreferenceLike;
2121
session?: ClientSession;
22-
/** @internal */
22+
/**
23+
* @experimental
24+
* Specifies the time an operation will run until it throws a timeout error. Note that if
25+
* `maxTimeMS` is provided in the command in addition to setting `timeoutMS` in the options, then
26+
* the original value of `maxTimeMS` will be overwritten.
27+
*/
2328
timeoutMS?: number;
24-
/** @internal */
29+
/**
30+
* @public
31+
* @experimental
32+
* Specifies how `timeoutMS` is applied to the cursor. Can be either `'cursorLifeTime'` or `'iteration'`
33+
* When set to `'iteration'`, the deadline specified by `timeoutMS` applies to each call of
34+
* `cursor.next()`.
35+
* When set to `'cursorLifetime'`, the deadline applies to the life of the entire cursor.
36+
*
37+
* Depending on the type of cursor being used, this option has different default values.
38+
* For non-tailable cursors, this value defaults to `'cursorLifetime'`
39+
* For tailable cursors, this value defaults to `'iteration'` since tailable cursors, by
40+
* definition can have an arbitrarily long lifetime.
41+
*
42+
* @example
43+
* ```ts
44+
* const cursor = collection.find({}, {timeoutMS: 100, timeoutMode: 'iteration'});
45+
* for await (const doc of cursor) {
46+
* // process doc
47+
* // This will throw a timeout error if any of the iterator's `next()` calls takes more than 100ms, but
48+
* // will continue to iterate successfully otherwise, regardless of the number of batches.
49+
* }
50+
* ```
51+
*
52+
* @example
53+
* ```ts
54+
* const cursor = collection.find({}, { timeoutMS: 1000, timeoutMode: 'cursorLifetime' });
55+
* const docs = await cursor.toArray(); // This entire line will throw a timeout error if all batches are not fetched and returned within 1000ms.
56+
* ```
57+
*/
2558
timeoutMode?: CursorTimeoutMode;
2659
tailable?: boolean;
2760
awaitData?: boolean;

src/db.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,10 @@ export interface DbOptions extends BSONSerializeOptions, WriteConcernOptions {
9797
readConcern?: ReadConcern;
9898
/** Should retry failed writes */
9999
retryWrites?: boolean;
100-
/** @internal TODO(NODE-5688): make this public */
100+
/**
101+
* @experimental
102+
* Specifies the time an operation will run until it throws a timeout error
103+
*/
101104
timeoutMS?: number;
102105
}
103106

@@ -222,8 +225,7 @@ export class Db {
222225
return this.s.namespace.toString();
223226
}
224227

225-
/** @internal */
226-
get timeoutMS(): number | undefined {
228+
public get timeoutMS(): number | undefined {
227229
return this.s.options?.timeoutMS;
228230
}
229231

src/error.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -865,7 +865,6 @@ export class MongoUnexpectedServerResponseError extends MongoRuntimeError {
865865
* @category Error
866866
*
867867
* This error is thrown when an operation could not be completed within the specified `timeoutMS`.
868-
* TODO(NODE-5688): expand this documentation.
869868
*
870869
* @example
871870
* ```ts

src/gridfs/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,11 @@ export interface GridFSBucketOptions extends WriteConcernOptions {
3838
chunkSizeBytes?: number;
3939
/** Read preference to be passed to read operations */
4040
readPreference?: ReadPreference;
41-
/** @internal TODO(NODE-5688): make this public */
41+
/**
42+
* @experimental
43+
* Specifies the lifetime duration of a gridFS stream. If any async operations are in progress
44+
* when this timeout expires, the stream will throw a timeout error.
45+
*/
4246
timeoutMS?: number;
4347
}
4448

src/index.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ export {
3737
Timestamp,
3838
UUID
3939
} from './bson';
40-
export { AnyBulkWriteOperation, BulkWriteOptions, MongoBulkWriteError } from './bulk/common';
40+
export {
41+
type AnyBulkWriteOperation,
42+
type BulkWriteOptions,
43+
MongoBulkWriteError
44+
} from './bulk/common';
4145
export { ClientEncryption } from './client-side-encryption/client_encryption';
4246
export { ChangeStreamCursor } from './cursor/change_stream_cursor';
4347
export {
@@ -111,7 +115,7 @@ export { AutoEncryptionLoggerLevel } from './client-side-encryption/auto_encrypt
111115
export { GSSAPICanonicalizationValue } from './cmap/auth/gssapi';
112116
export { AuthMechanism } from './cmap/auth/providers';
113117
export { Compressor } from './cmap/wire_protocol/compression';
114-
export { CURSOR_FLAGS, type CursorTimeoutMode } from './cursor/abstract_cursor';
118+
export { CURSOR_FLAGS, CursorTimeoutMode } from './cursor/abstract_cursor';
115119
export { MongoErrorLabel } from './error';
116120
export { ExplainVerbosity } from './explain';
117121
export { ServerApiVersion } from './mongo_client';

src/mongo_client.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,10 @@ export type SupportedNodeConnectionOptions = SupportedTLSConnectionOptions &
130130
export interface MongoClientOptions extends BSONSerializeOptions, SupportedNodeConnectionOptions {
131131
/** Specifies the name of the replica set, if the mongod is a member of a replica set. */
132132
replicaSet?: string;
133-
/** @internal TODO(NODE-5688): This option is in development and currently has no behaviour. */
133+
/**
134+
* @experimental
135+
* Specifies the time an operation will run until it throws a timeout error
136+
*/
134137
timeoutMS?: number;
135138
/** Enables or disables TLS/SSL for the connection. */
136139
tls?: boolean;
@@ -488,7 +491,6 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
488491
return this.s.bsonOptions;
489492
}
490493

491-
/** @internal */
492494
get timeoutMS(): number | undefined {
493495
return this.s.options.timeoutMS;
494496
}
@@ -1029,6 +1031,5 @@ export interface MongoOptions
10291031
* TODO: NODE-5671 - remove internal flag
10301032
*/
10311033
mongodbLogPath?: 'stderr' | 'stdout' | MongoDBLogWritable;
1032-
/** @internal TODO(NODE-5688): make this public */
10331034
timeoutMS?: number;
10341035
}

src/operations/indexes.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { Document } from '../bson';
22
import { CursorResponse } from '../cmap/wire_protocol/responses';
33
import type { Collection } from '../collection';
4-
import { type AbstractCursorOptions, type CursorTimeoutMode } from '../cursor/abstract_cursor';
4+
import { type AbstractCursorOptions } from '../cursor/abstract_cursor';
55
import { MongoCompatibilityError } from '../error';
66
import { type OneOrMore } from '../mongo_types';
77
import type { Server } from '../sdam/server';
@@ -361,8 +361,6 @@ export class DropIndexOperation extends CommandOperation<Document> {
361361

362362
/** @public */
363363
export type ListIndexesOptions = AbstractCursorOptions & {
364-
/** @internal TODO(NODE-5688): make this public */
365-
timeoutMode?: CursorTimeoutMode;
366364
/** @internal */
367365
omitMaxTimeMS?: boolean;
368366
};

src/operations/operation.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { type BSONSerializeOptions, type Document, resolveBSONOptions } from '..
22
import { ReadPreference, type ReadPreferenceLike } from '../read_preference';
33
import type { Server } from '../sdam/server';
44
import type { ClientSession } from '../sessions';
5-
import { type Timeout, type TimeoutContext } from '../timeout';
5+
import { type TimeoutContext } from '../timeout';
66
import type { MongoDBNamespace } from '../utils';
77

88
export const Aspect = {
@@ -35,7 +35,10 @@ export interface OperationOptions extends BSONSerializeOptions {
3535
/** @internal Hint to `executeOperation` to omit maxTimeMS */
3636
omitMaxTimeMS?: boolean;
3737

38-
/** @internal TODO(NODE-5688): make this public */
38+
/**
39+
* @experimental
40+
* Specifies the time an operation will run until it throws a timeout error
41+
*/
3942
timeoutMS?: number;
4043
}
4144

@@ -61,9 +64,7 @@ export abstract class AbstractOperation<TResult = any> {
6164

6265
options: OperationOptions;
6366

64-
/** @internal */
65-
timeout?: Timeout;
66-
/** @internal */
67+
/** Specifies the time an operation will run until it throws a timeout error. */
6768
timeoutMS?: number;
6869

6970
[kSession]: ClientSession | undefined;

src/operations/run_command.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ export type RunCommandOptions = {
1515
session?: ClientSession;
1616
/** The read preference */
1717
readPreference?: ReadPreferenceLike;
18-
/** @internal */
18+
/**
19+
* @experimental
20+
* Specifies the time an operation will run until it throws a timeout error
21+
*/
1922
timeoutMS?: number;
2023
/** @internal */
2124
omitMaxTimeMS?: boolean;

src/sessions.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export interface EndSessionOptions {
103103
force?: boolean;
104104
forceClear?: boolean;
105105

106-
/** @internal */
106+
/** Specifies the time an operation will run until it throws a timeout error */
107107
timeoutMS?: number;
108108
}
109109

@@ -145,7 +145,10 @@ export class ClientSession
145145
[kPinnedConnection]?: Connection;
146146
/** @internal */
147147
[kTxnNumberIncrement]: number;
148-
/** @internal */
148+
/**
149+
* @experimental
150+
* Specifies the time an operation in a given `ClientSession` will run until it throws a timeout error
151+
*/
149152
timeoutMS?: number;
150153

151154
/** @internal */
@@ -710,6 +713,9 @@ export class ClientSession
710713
* `Promise.allSettled`, `Promise.race`, etc to parallelize operations inside a transaction is
711714
* undefined behaviour.
712715
*
716+
* **IMPORTANT:** When running an operation inside a `withTransaction` callback, if it is not
717+
* provided the explicit session in its options, it will not be part of the transaction and it will not respect timeoutMS.
718+
*
713719
*
714720
* @remarks
715721
* - If all operations successfully complete and the `commitTransaction` operation is successful, then the provided function will return the result of the provided function.

test/integration/client-side-operations-timeout/node_csot.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
type CommandStartedEvent,
1919
type CommandSucceededEvent,
2020
Connection,
21+
CursorTimeoutMode,
2122
type Db,
2223
type FindCursor,
2324
GridFSBucket,
@@ -423,7 +424,7 @@ describe('CSOT driver tests', metadata, () => {
423424
const cursor = client
424425
.db('db')
425426
.collection('coll')
426-
.find({}, { batchSize: 3, timeoutMode: 'iteration', timeoutMS: 10 })
427+
.find({}, { batchSize: 3, timeoutMode: CursorTimeoutMode.ITERATION, timeoutMS: 10 })
427428
.limit(3);
428429

429430
const maybeError = await cursor.next().then(

0 commit comments

Comments
 (0)