diff --git a/source/client-side-operations-timeout/client-side-operations-timeout.md b/source/client-side-operations-timeout/client-side-operations-timeout.md index b99754d6ae..607ec76d55 100644 --- a/source/client-side-operations-timeout/client-side-operations-timeout.md +++ b/source/client-side-operations-timeout/client-side-operations-timeout.md @@ -428,6 +428,20 @@ check the command document for the presence of a `maxTimeMS` field. See [runCommand behavior](#runcommand-behavior). +### Explain + +> [!NOTE] +> This portion of the specification is only relevant for drivers that provide `explain` helpers. + +When `timeoutMS` is specified, drivers MUST provide a way to specify timeoutMS that results in maxTimeMS being set on +the `explain` command. For example, Node's implementation might look like: + +```typescript +collection.find({}).explain({ timeoutMS: 1000 }); +// sends: +{ explain: { find: ... }, maxTimeMS: } +``` + ## Test Plan See the [README.rst](tests/README.md) in the tests directory. @@ -651,6 +665,7 @@ timeout for each database operation. This would mimic using `timeoutMode=ITERATI ## Changelog +- 2024-09-12: Specify that explain helpers support support timeoutMS. - 2023-12-07: Migrated from reStructuredText to Markdown. - 2022-11-17: Use minimum RTT for maxTimeMS calculation instead of 90th percentile RTT. - 2022-10-05: Remove spec front matter. diff --git a/source/crud/crud.md b/source/crud/crud.md index cd9389c4e5..a327949058 100644 --- a/source/crud/crud.md +++ b/source/crud/crud.md @@ -104,6 +104,9 @@ Drivers MUST enforce timeouts for all operations per the [Client Side Operations Timeout](../client-side-operations-timeout/client-side-operations-timeout.md) specification. All operations that return cursors MUST support the timeout options documented in the [Cursors](../client-side-operations-timeout/client-side-operations-timeout.md#cursors) section of that specification. +All explain helpers MUST support the timeout options documented in the +[Explain Helpers](../client-side-operations-timeout/client-side-operations-timeout.md#explain) section of that +specification. ### API @@ -178,9 +181,6 @@ interface Collection { * as it would be impossible to be forwards and backwards compatible. Let the server * handle the validation. * - * Note: If $explain is specified in the modifiers, the return value is a single - * document. This could cause problems for static languages using strongly typed entities. - * * Note: result iteration should be backed by a cursor. Depending on the implementation, * the cursor may back the returned Iterable instance or an iterator that it produces. * @@ -2199,6 +2199,47 @@ the [$readPreference global command argument](../message/OP_MSG.md#global-comman [passing read preference to mongos and load balancers](../server-selection/server-selection.md#passing-read-preference-to-mongos-and-load-balancers) (if applicable). +### Explain + +> [!NOTE] +> Explain helpers are optional. Drivers that do not provide explain helpers may ignore this section. + +```typescript +interface ExplainOptions { + /** + * The maximum amount of time to allow the explain to run. + * + * This option is sent only if the caller explicitly provides a value. The default is to not send a value. + * + * NOTE: This option is deprecated in favor of timeoutMS. + */ + maxTimeMS: Optional; +} +``` + +Drivers MUST ensure that its helper permits users to specify a timeout (maxTimeMS or timeoutMS) for the explain command +specifically. An example, using Node, might look like: + +```typescript +collection.find({ name: 'john doe' }).explain({ maxTimeMS: 1000 }); + +// sends: +{ + explain: { find: , query: { name: 'john doe' } }, + maxTimeMS: 1000 +} + +collection.find({ name: 'john doe' }).explain({ timeoutMS: 1000 }); + +// sends: +{ + explain: { find: , query: { name: 'john doe' } }, + maxTimeMS: <1000 - min rtt> +} +``` + +Drivers MUST document how users can specify options on their explain helpers. + ## Test Plan See the [README](tests/README.md) for tests. @@ -2311,6 +2352,13 @@ api be consistent with the rest of the methods in the CRUD family of operations. able to be used as this change is non-backwards breaking. Any driver which implemented the fluent bulk API should deprecate it and drivers that have not built it should not do so. +Q: Should drivers offer explain helpers?\ +Originally, it was determined that explain should not be exposed via +specialized APIs in drivers because it it was deemed to be an unusual use-case for a driver. We'd like users to use the +shell for this purpose. However, explain is still possible from a driver. Some drivers have historically provided +explain helpers and continue to do so. Drivers that do not offer explain helpers can run explain commands using the +runCommand API. + Q: What about explain? Explain has been determined to be not a normal use-case for a driver. We'd like users to use the shell for this purpose. @@ -2380,6 +2428,8 @@ aforementioned allowance in the SemVer spec. ## Changelog +- 2024-09-12: Specify that explain helpers support maxTimeMS. + - 2024-02-20: Migrated from reStructuredText to Markdown. - 2022-10-05: Remove spec front matter and reformat changelog. diff --git a/source/crud/tests/README.md b/source/crud/tests/README.md index 261d81c96f..8d091f443d 100644 --- a/source/crud/tests/README.md +++ b/source/crud/tests/README.md @@ -677,3 +677,19 @@ InsertOne { Execute `bulkWrite` on `client` with `model`. Assert that an error (referred to as `error`) is returned. Assert that `error` is a client error containing the message: "bulkWrite does not currently support automatic encryption". + +### 14. `explain` helpers allow users to specify `maxTimeMS` + +Drivers that provide multiple APIs to specify explain should ensure this test is run at least once with each distinct +API. For example, the Node driver runs this test with option API (`collection.find({}, { explain: ... })`) and the +fluent API (`collection.find({}).explain(...)`). + +Create a MongoClient with command monitoring enabled (referred to as `client`). + +Create a collection, referred to as `collection`, with the namespace `explain-test.collection`. + +Run an explained find on `collection`. The find will have the query predicate `{ name: 'john doe' }`. Specify a +maxTimeMS value of 2000ms for the `explain`. + +Obtain the command started event for the explain. Confirm that the top-level explain command should has a `maxTimeMS` +value of `2000`.