Skip to content

Commit 78f1fd3

Browse files
authored
SWIFT-776 Add transaction retry examples (#479)
1 parent 8435316 commit 78f1fd3

File tree

4 files changed

+47
-17
lines changed

4 files changed

+47
-17
lines changed

Guides/Transactions.md

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,22 @@ Transactions in the driver must be started on a `ClientSession` using `startTran
88

99
## Examples
1010

11+
Below are some basic examples of using transactions in `MongoSwift`. In realistic use cases, transactions would ideally be retried when facing transient errors. For more detailed examples featuring retry logic, see the [official MongoDB documentation's examples](https://docs.mongodb.com/manual/core/transactions-in-applications/#txn-core-api).
12+
1113
### Transaction that Atomically Moves a `Document` from One `MongoCollection` to Another
1214

1315
The transaction below atomically deletes the document `{ "hello": "world" }` from the collection `test.src` and inserts the document in the collection `test.dest`. This ensures that the document exists in either `test.src` or `test.dest`, but not both or neither. Executing the delete and insert non-atomically raises the following issues:
1416
- A race between `deleteOne()` and `insertOne()` where the document does not exist in either collection.
1517
- If `deleteOne()` fails and `insertOne()` succeeds, the document exists in both collections.
1618
- If `deleteOne()` succeeds and `insertOne()` fails, the document does not exist in either collection.
1719

20+
In order to achieve the highest safety guarantees that MongoDB transactions offer, a "snapshot" read concern and a "majority" write concern must be used. To see the varying levels safety provided by different read concern / write concern configurations, see the [official MongoDB documentation](https://docs.mongodb.com/manual/core/transactions/#read-concern-write-concern-read-preference).
21+
22+
Transactions will inherit the read concern / write concern / read preference specified on the client that started the transaction's session unless they were also specified in either the default transaction options or in the transaction options passed to `startTransaction`. See the below sections on how to do either.
23+
24+
**Note:** All operations executed as part of a transaction will use the transaction's read concern / write concern / read preference. Any of those options specified on the database or collection that executes the operation or on a per-operation basis will be _ignored_.
1825
```swift
19-
let client = try MongoClient(using: elg)
26+
let client = try MongoClient(using: elg, options: ClientOptions(readConcern: .snapshot, writeConcern: .majority))
2027
let session = client.startSession()
2128

2229
let db = client.db("test")
@@ -43,9 +50,9 @@ The default transaction options specified below apply to any transaction started
4350
```swift
4451
let txnOpts = TransactionOptions(
4552
maxCommitTimeMS: 30,
46-
readConcern: ReadConcern(.local),
47-
readPreference: .primaryPreferred,
48-
writeConcern: try WriteConcern(w: .majority)
53+
readConcern: .snapshot,
54+
readPreference: .primary,
55+
writeConcern: .majority
4956
)
5057

5158
let client = try MongoClient(using: elg)
@@ -63,17 +70,17 @@ session.startTransaction().flatMap { _ in
6370

6471
### Transaction with Custom Transaction Options
6572

66-
**Note**:: Any transaction options provided directly to `startTransaction()` override the default transaction options for the session. More so, the default transaction options for the session override any options inherited from the client.
73+
**Note**: Any transaction options provided directly to `startTransaction()` override the default transaction options for the session. More so, the default transaction options for the session override any options inherited from the client.
6774

6875
```swift
6976
let client = try MongoClient(using: elg)
7077
let session = client.startSession()
7178

7279
let txnOpts = TransactionOptions(
7380
maxCommitTimeMS: 30,
74-
readConcern: ReadConcern(.local),
75-
readPreference: .primaryPreferred,
76-
writeConcern: try WriteConcern(w: .majority)
81+
readConcern: .snapshot,
82+
readPreference: .primary,
83+
writeConcern: .majority
7784
)
7885

7986
session.startTransaction(options: txnOpts).flatMap { _ in
@@ -87,4 +94,6 @@ session.startTransaction(options: txnOpts).flatMap { _ in
8794
```
8895

8996
## See Also
90-
- [MongoDB Transactions documentation](https://docs.mongodb.com/manual/core/transactions/)
97+
- [MongoDB Transactions documentation](https://docs.mongodb.com/manual/core/transactions/)
98+
- [MongoDB Driver Transactions Core API](https://docs.mongodb.com/manual/core/transactions-in-applications/#txn-core-api)
99+
- [MongoDB Transactions and Read Concern / Write Concern / Read Preference](https://docs.mongodb.com/manual/core/transactions/#read-concern-write-concern-read-preference)

Sources/MongoSwift/ClientSession.swift

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -340,10 +340,18 @@ public final class ClientSession {
340340
}
341341

342342
/**
343-
* Starts a multi-document transaction for all subsequent operations in this session. Any options provided in
344-
* `options` override the default transaction options for this session and any options inherited from
345-
* `MongoClient`. The transaction must be completed with `commitTransaction` or `abortTransaction`. An in-progress
346-
* transaction is automatically aborted when `ClientSession.end()` is called.
343+
* Starts a multi-document transaction for all subsequent operations in this session.
344+
*
345+
* Any options provided in `options` will override the default transaction options for this session and any options
346+
* inherited from `MongoClient`.
347+
*
348+
* Operations executed as part of the transaction will use the options specified on the transaction, and those
349+
* options cannot be overridden at a per-operation level. Any options that overlap with the transaction options
350+
* which can be specified at a per operation level (e.g. write concern) _will be ignored_ if specified. This
351+
* includes options specified at the database or collection level on the object used to execute an operation.
352+
*
353+
* The transaction must be completed with `commitTransaction` or `abortTransaction`. An in-progress transaction is
354+
* automatically aborted when `ClientSession.end()` is called.
347355
*
348356
* - Parameters:
349357
* - options: The options to use when starting this transaction

Sources/MongoSwift/Operations/StartSessionOperation.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ public struct ClientSessionOptions {
99
public var causalConsistency: Bool?
1010

1111
/// The default `TransactionOptions` to use for transactions started on this session.
12+
///
13+
/// These may be overridden by options provided directly to `ClientSession.startTransaction`.
14+
///
15+
/// If this option is not specified, the options will be inherited from the client that started this session where
16+
/// applicable (e.g. write concern).
1217
public var defaultTransactionOptions: TransactionOptions?
1318

1419
/// Convenience initializer allowing any/all parameters to be omitted.

Sources/MongoSwiftSync/ClientSession.swift

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,18 @@ public final class ClientSession {
9898
}
9999

100100
/**
101-
* Starts a multi-document transaction for all subsequent operations in this session. Any options provided in
102-
* `options` override the default transaction options for this session and any options inherited from
103-
* `MongoClient`. The transaction must be completed with `commitTransaction` or `abortTransaction`. An in-progress
104-
* transaction is automatically aborted when `ClientSession` goes out of scope.
101+
* Starts a multi-document transaction for all subsequent operations in this session.
102+
*
103+
* Any options provided in `options` will override the default transaction options for this session and any options
104+
* inherited from `MongoClient`.
105+
*
106+
* Operations executed as part of the transaction will use the options specified on the transaction, and those
107+
* options cannot be overridden at a per-operation level. Any options that overlap with the transaction options
108+
* which can be specified at a per operation level (e.g. write concern) _will be ignored_ if specified. This
109+
* includes options specified at the database or collection level on the object used to execute an operation.
110+
*
111+
* The transaction must be completed with `commitTransaction` or `abortTransaction`. An in-progress transaction is
112+
* automatically aborted when `ClientSession.end()` is called.
105113
*
106114
* - Parameters:
107115
* - options: The options to use when starting this transaction

0 commit comments

Comments
 (0)