Skip to content

Commit

Permalink
DRIVERS-1256: specify how drivers set timeouts on explain commands (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
baileympearson committed Sep 12, 2024
1 parent 2665a24 commit 124cc36
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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: <remaining timeoutMS - min rtt>}
```

## Test Plan

See the [README.md](tests/README.md) in the tests directory.
Expand Down Expand Up @@ -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.
Expand Down
56 changes: 53 additions & 3 deletions source/crud/crud.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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.
*
Expand Down Expand Up @@ -2201,6 +2201,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<Int64>;
}
```
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: <collection>, query: { name: 'john doe' } },
maxTimeMS: 1000
}

collection.find({ name: 'john doe' }).explain({ timeoutMS: 1000 });

// sends:
{
explain: { find: <collection>, 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.
Expand Down Expand Up @@ -2313,6 +2354,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.
Expand Down Expand Up @@ -2382,6 +2430,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.
Expand Down
16 changes: 16 additions & 0 deletions source/crud/tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.

0 comments on commit 124cc36

Please sign in to comment.