Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 4 additions & 12 deletions src/change_stream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import type { AggregateOptions } from './operations/aggregate';
import type { OperationParent } from './operations/command';
import { DeprioritizedServers } from './sdam/server_selection';
import type { ServerSessionId } from './sessions';
import { CSOTTimeoutContext, type TimeoutContext } from './timeout';
import { type TimeoutContext } from './timeout';
import { type AnyOptions, getTopology, type MongoDBNamespace, squashError } from './utils';

const CHANGE_DOMAIN_TYPES = {
Expand Down Expand Up @@ -647,18 +647,17 @@ export class ChangeStream<

this.pipeline = pipeline;
this.options = { ...options };
let serverSelectionTimeoutMS: number;
// timeoutMS and timeoutMode are no-ops, so they must never reach the cursor options
this.options.timeoutMS = undefined;
this.options.timeoutMode = undefined;
delete this.options.writeConcern;

if (parent instanceof Collection) {
this.type = CHANGE_DOMAIN_TYPES.COLLECTION;
serverSelectionTimeoutMS = parent.s.db.client.options.serverSelectionTimeoutMS;
} else if (parent instanceof Db) {
this.type = CHANGE_DOMAIN_TYPES.DATABASE;
serverSelectionTimeoutMS = parent.client.options.serverSelectionTimeoutMS;
} else if (parent instanceof MongoClient) {
this.type = CHANGE_DOMAIN_TYPES.CLUSTER;
serverSelectionTimeoutMS = parent.options.serverSelectionTimeoutMS;
} else {
throw new MongoChangeStreamError(
'Parent provided to ChangeStream constructor must be an instance of Collection, Db, or MongoClient'
Expand Down Expand Up @@ -690,13 +689,6 @@ export class ChangeStream<
this.cursorStream?.removeAllListeners('data');
}
});

if (this.options.timeoutMS != null) {
this.timeoutContext = new CSOTTimeoutContext({
timeoutMS: this.options.timeoutMS,
serverSelectionTimeoutMS
});
}
}

/** The cached resume token that is used to resume after the most recently returned change. */
Expand Down
28 changes: 1 addition & 27 deletions src/client-side-encryption/client_encryption.ts
Original file line number Diff line number Diff line change
Expand Up @@ -987,34 +987,8 @@ export interface ClientEncryptionOptions {
keyExpirationMS?: number;

/**
* @experimental
* The timeout setting to be used for all the operations on ClientEncryption.
*
* When provided, `timeoutMS` is used as the timeout for each operation executed on
* the ClientEncryption object. For example:
*
* ```typescript
* const clientEncryption = new ClientEncryption(client, {
* timeoutMS: 1_000
* kmsProviders: { local: { key: '<KEY>' } }
* });
*
* // `1_000` is used as the timeout for createDataKey call
* await clientEncryption.createDataKey('local');
* ```
*
* If `timeoutMS` is configured on the provided client, the client's `timeoutMS` value
* will be used unless `timeoutMS` is also provided as a client encryption option.
*
* ```typescript
* const client = new MongoClient('<uri>', { timeoutMS: 2_000 });
*
* // timeoutMS is set to 1_000 on clientEncryption
* const clientEncryption = new ClientEncryption(client, {
* timeoutMS: 1_000
* kmsProviders: { local: { key: '<KEY>' } }
* });
* ```
* @deprecated `timeoutMS` has no effect and will be removed in a future release.
*/
timeoutMS?: number;
}
Expand Down
1 change: 1 addition & 0 deletions src/client-side-encryption/kms_options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export type ClientEncryptionSocketOptions = Pick<
export type KMSConnectCallback = (options: {
host: string;
port: number;
/** @deprecated `timeoutMS` has no effect and will be removed in a future release. */
timeoutMS?: number;
signal: AbortSignal;
}) => Promise<Duplex>;
61 changes: 4 additions & 57 deletions src/collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ export interface CollectionOptions extends BSONSerializeOptions, WriteConcernOpt
/** The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). */
readPreference?: ReadPreferenceLike;
/**
* @experimental
* Specifies the time an operation will run until it throws a timeout error
* @deprecated `timeoutMS` has no effect and will be removed in a future release.
*/
timeoutMS?: number;
}
Expand Down Expand Up @@ -277,8 +277,9 @@ export class Collection<TSchema extends Document = Document> {
this.s.collectionHint = normalizeHintField(v);
}

/** @deprecated `timeoutMS` has no effect and will be removed in a future release. */
public get timeoutMS(): number | undefined {
return this.s.options.timeoutMS;
return undefined;
}

/**
Expand Down Expand Up @@ -1170,60 +1171,6 @@ export class Collection<TSchema extends Document = Document> {
* expectType<Schema>(change.fullDocument);
* });
* ```
*
* @remarks
* When `timeoutMS` is configured for a change stream, it will have different behaviour depending
* on whether the change stream is in iterator mode or emitter mode. In both cases, a change
* stream will time out if it does not receive a change event within `timeoutMS` of the last change
* event.
*
* Note that if a change stream is consistently timing out when watching a collection, database or
* client that is being changed, then this may be due to the server timing out before it can finish
* processing the existing oplog. To address this, restart the change stream with a higher
* `timeoutMS`.
*
* If the change stream times out the initial aggregate operation to establish the change stream on
* the server, then the client will close the change stream. If the getMore calls to the server
* time out, then the change stream will be left open, but will throw a MongoOperationTimeoutError
* when in iterator mode and emit an error event that returns a MongoOperationTimeoutError in
* emitter mode.
*
* To determine whether or not the change stream is still open following a timeout, check the
* {@link ChangeStream.closed} getter.
*
* @example
* In iterator mode, if a next() call throws a timeout error, it will attempt to resume the change stream.
* The next call can just be retried after this succeeds.
* ```ts
* const changeStream = collection.watch([], { timeoutMS: 100 });
* try {
* await changeStream.next();
* } catch (e) {
* if (e instanceof MongoOperationTimeoutError && !changeStream.closed) {
* await changeStream.next();
* }
* throw e;
* }
* ```
*
* @example
* In emitter mode, if the change stream goes `timeoutMS` without emitting a change event, it will
* emit an error event that returns a MongoOperationTimeoutError, but will not close the change
* stream unless the resume attempt fails. There is no need to re-establish change listeners as
* this will automatically continue emitting change events once the resume attempt completes.
*
* ```ts
* const changeStream = collection.watch([], { timeoutMS: 100 });
* changeStream.on('change', console.log);
* changeStream.on('error', e => {
* if (e instanceof MongoOperationTimeoutError && !changeStream.closed) {
* // do nothing
* } else {
* changeStream.close();
* }
* });
* ```
*
* @param pipeline - An array of {@link https://www.mongodb.com/docs/manual/reference/operator/aggregation-pipeline/|aggregation pipeline stages} through which to pass change stream documents. This allows for filtering (using $match) and manipulating the change stream documents.
* @param options - Optional settings for the command
* @typeParam TLocal - Type of the data being detected by the change stream
Expand Down Expand Up @@ -1316,7 +1263,7 @@ export class Collection<TSchema extends Document = Document> {
? null
: indexNameOrOptions;

return new ListSearchIndexesCursor(this as TODO_NODE_3286, indexName, options);
return new ListSearchIndexesCursor(this as TODO_NODE_3286, indexName, { ...options });
}

/**
Expand Down
20 changes: 15 additions & 5 deletions src/connection_string.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ export function parseOptions(
);
}

if (!isReadPreferenceTags && values.includes('')) {
if (!isReadPreferenceTags && values.includes('') && !isIgnoredOption(key)) {
throw new MongoAPIError(`URI option "${key}" cannot be specified with no value`);
}

Expand Down Expand Up @@ -416,12 +416,14 @@ export function parseOptions(
setOption(mongoOptions, key, descriptor, [DEFAULT_OPTIONS.get(key)]);
}
} else {
const { deprecated } = descriptor;
const { deprecated, ignored } = descriptor;
if (deprecated) {
const deprecatedMsg = typeof deprecated === 'string' ? `: ${deprecated}` : '';
emitWarning(`${key} is a deprecated option${deprecatedMsg}`);
}

if (ignored) continue;
Comment thread
tadjik1 marked this conversation as resolved.
Resolved

setOption(mongoOptions, key, descriptor, values);
}
}
Expand Down Expand Up @@ -659,6 +661,13 @@ function normalizeSrvAllowedHostsSuffix(value: string): string {
return `.${suffix}`;
}

/** Ignored options are never validated, since their values have no effect. */
function isIgnoredOption(key: string): boolean {
return Object.entries(OPTIONS).some(
([name, descriptor]) => descriptor.ignored && name.toLowerCase() === key.toLowerCase()
);
}

function setOption(
mongoOptions: any,
key: string,
Expand Down Expand Up @@ -713,6 +722,8 @@ interface OptionDescriptor {
default?: any;

deprecated?: boolean | string;
/** The option is accepted but has no effect, so it is never stored on the resolved options. */
ignored?: boolean;
/**
* @param name - the original option name
* @param options - the options so far for resolution
Expand Down Expand Up @@ -1180,7 +1191,6 @@ export const OPTIONS = {
type: 'string'
},
socketTimeoutMS: {
// TODO(NODE-6491): deprecated: 'Please use timeoutMS instead',
default: 0,
type: 'uint'
},
Expand Down Expand Up @@ -1228,7 +1238,8 @@ export const OPTIONS = {
type: 'boolean'
},
timeoutMS: {
type: 'uint'
deprecated: 'timeoutMS has no effect and will be removed in a future release',
ignored: true
},
tls: {
type: 'boolean'
Expand Down Expand Up @@ -1282,7 +1293,6 @@ export const OPTIONS = {
}
},
waitQueueTimeoutMS: {
// TODO(NODE-6491): deprecated: 'Please use timeoutMS instead',
default: 0,
type: 'uint'
},
Expand Down
Loading
Loading