Skip to content
56 changes: 43 additions & 13 deletions source/sessions/snapshot-sessions.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,24 +63,28 @@ response. The `atClusterTime` field represents the timestamp of the read and is
## Specification

An application requests snapshot reads by creating a `ClientSession` with options that specify that snapshot reads are
desired. An application then passes the session as an argument to methods in the `MongoDatabase` and `MongoCollection`
classes. Read operations (find/aggregate/distinct) performed against that session will be read from the same snapshot.
desired and optionally specifying a `snapshotTime`. An application then passes the session as an argument to methods in
the `MongoDatabase` and `MongoCollection` classes. Read operations (find/aggregate/distinct) performed against that
session will be read from the same snapshot.

## High level summary of the API changes for snapshot reads

Snapshot reads are built on top of client sessions.

Applications will start a new client session for snapshot reads like this:
Applications will start a new client session for snapshot reads and possibly retrieve the snapshot time like this:

```typescript
options = new SessionOptions(snapshot = true);
options = new SessionOptions(snapshot = true, snapshotTime = timestampValue);
session = client.startSession(options);
snapshotTime = session.snapshotTime;
```

All read operations performed using this session will be read from the same snapshot.

If no value is provided for `snapshot` a value of false is implied. There are no MongoDatabase, MongoClient, or
MongoCollection API changes.
If no value is provided for `snapshot` a value of false is implied. `snapshotTime` is an optional parameter and if not
passed the snapshot time will be set internally after the first find/aggregate/distinct operation inside the session.

There are no MongoDatabase, MongoClient, or MongoCollection API changes.

## SessionOptions changes

Expand All @@ -89,14 +93,16 @@ MongoCollection API changes.
```typescript
class SessionOptions {
Optional<bool> snapshot;
Optional<BsonTimestamp> snapshotTime;

// other options defined by other specs
}
```

In order to support snapshot reads a new property named `snapshot` is added to `SessionOptions`. Applications set
`snapshot` when starting a client session to indicate whether they want snapshot reads. All read operations performed
using that client session will share the same snapshot.
In order to support snapshot reads two properties called `snapshot` and `snapshotTime` are added to `SessionOptions`.
Applications set `snapshot` when starting a client session to indicate whether they want snapshot reads and optionally
set `snapshotTime` to specify the desired snapshot time beforehand. All read operations performed using that client
session will share the same snapshot.

Each new member is documented below.

Expand All @@ -110,8 +116,29 @@ Snapshot reads and causal consistency are mutually exclusive. Therefore if `snap
`causalConsistency` must be false. Client MUST throw an error if both `snapshot` and `causalConsistency` are set to
true. Snapshot reads are supported on both primaries and secondaries.

### snapshotTime

Applications set `snapshotTime` when starting a snapshot session to specify the desired snapshot time.

Note that the `snapshotTime` property is optional. The default value of this property is null.

Client MUST throw an error if `snapshotTime` is set and `snapshot` is not set to true.

## ClientSession changes

A readonly property called `snapshotTime` will be added to `ClientSession` that allows applications to retrieve the
snapshot time of the session:

```typescript
class ClientSession {
readonly Optional<BsonTimestamp> snapshotTime;

// other options defined by other specs
}
```

Getting the value of `snapshotTime` on a non-snapshot session MUST raise an error.

Transactions are not allowed with snapshot sessions. Calling `session.startTransaction(options)` on a snapshot session
MUST raise an error.

Expand All @@ -123,10 +150,12 @@ MUST raise an error.

There are no new server commands related to snapshot reads. Instead, snapshot reads are implemented by:

1. Saving the `atClusterTime` returned by 5.0+ servers for the first find/aggregate/distinct operation in a private
`snapshotTime` property of the `ClientSession` object. Drivers MUST save `atClusterTime` in the `ClientSession`
object.
2. Passing that `snapshotTime` in the `atClusterTime` field of the `readConcern` field for subsequent snapshot read
1. If `snapshotTime` is specified in `SessionOptions`, saving the value in a `snapshotTime` property of the
`ClientSession`.
2. If `snapshotTime` is not specified in `SessionOptions`, saving the `atClusterTime` returned by 5.0+ servers for the
first find/aggregate/distinct operation in a `snapshotTime` property of the `ClientSession` object. Drivers MUST
save `atClusterTime` in the `ClientSession` object.
3. Passing that `snapshotTime` in the `atClusterTime` field of the `readConcern` field for subsequent snapshot read
operations (i.e. find/aggregate/distinct commands).

## Server Command Responses
Expand Down Expand Up @@ -241,6 +270,7 @@ C# driver will provide the reference implementation. The corresponding ticket is

## Changelog

- 2025-09-23: Exposed snapshotTime to applications.
- 2024-05-08: Migrated from reStructuredText to Markdown.
- 2021-06-15: Initial version.
- 2021-06-28: Raise client side error on < 5.0.
Expand Down
25 changes: 25 additions & 0 deletions source/sessions/tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ As part of the test setup for these cases, create a `MongoClient` pointed at the
in the test case and verify that the test server does NOT define a value for `logicalSessionTimeoutMinutes` by sending a
hello command and checking the response.

## Specific operations and behaviour for unified tests

An operation on sessions called `getSnapshotTime` must be supported for unified tests. This operation returns the value
of `snapshotTime` on the session, so that it can be used in subsequent operations.

When parsing `snapshotTime` from `sessionOptions` for unified tests, the parsed string is the name of the key for the
actual value of `snapshotTime` to be found in the
[entity map](https://github.com/mongodb/specifications/blob/master/source/unified-test-format/unified-test-format.md#entity-map).

## Prose tests

### 1. Setting both `snapshot` and `causalConsistency` to true is not allowed
Expand Down Expand Up @@ -250,8 +259,24 @@ and configure a `MongoClient` with default options.
- Run a ping command using C1 and assert that `$clusterTime` sent is the same as the `clusterTime` recorded earlier.
This assertion proves that C1's `$clusterTime` was not advanced by gossiping through SDAM.

### 21. Having `snapshotTime` set and `snapshot` set to false is not allowed

Snapshot sessions tests require server of version 5.0 or higher and replica set or a sharded cluster deployment.

- Start a session by calling `startSession` with `snapshot = false` and `snapshotTime = new Timestamp(1)`.
- Assert that a client side error was raised.

### 22. Retrieving `snapshotTime` on a non-snapshot session raises an error

Snapshot sessions tests require server of version 5.0 or higher and replica set or a sharded cluster deployment.

- Start a session by calling `startSession` on with `snapshot = false`.
- Try to access the session's snapshot time.
- Assert that a client side error was raised.

## Changelog

- 2025-09-25: Added tests for snapshotTime.
- 2025-02-24: Test drivers do not gossip $clusterTime on SDAM.
- 2024-05-08: Migrated from reStructuredText to Markdown.
- 2019-05-15: Initial version.
Expand Down
Loading
Loading