-
Notifications
You must be signed in to change notification settings - Fork 65
/
Copy pathStartTransactionOperation.swift
90 lines (74 loc) · 2.99 KB
/
StartTransactionOperation.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import CLibMongoC
/// Options to use when starting a transaction.
public struct TransactionOptions {
/// The maximum amount of time to allow a single `commitTransaction` command to run.
public var maxCommitTimeMS: Int?
/// The `ReadConcern` to use for this transaction.
public var readConcern: ReadConcern?
/// The `ReadPreference` to use for this transaction.
public var readPreference: ReadPreference?
/// The `WriteConcern` to use for this transaction.
public var writeConcern: WriteConcern?
/// Convenience initializer allowing any/all parameters to be omitted.
public init(
maxCommitTimeMS: Int? = nil,
readConcern: ReadConcern? = nil,
readPreference: ReadPreference? = nil,
writeConcern: WriteConcern? = nil
) {
self.maxCommitTimeMS = maxCommitTimeMS
self.readConcern = readConcern
self.readPreference = readPreference
self.writeConcern = writeConcern
}
}
/// Internal helper function for providing a `mongoc_transaction_opt_t` that is only valid within the body of the
/// provided closure.
internal func withMongocTransactionOpts<T>(
copying options: TransactionOptions?,
_ body: (OpaquePointer) throws -> T
) rethrows -> T {
let optionsPtr: OpaquePointer = mongoc_transaction_opts_new()
defer { mongoc_transaction_opts_destroy(optionsPtr) }
if let readConcern = options?.readConcern {
readConcern.withMongocReadConcern { rcPtr in
mongoc_transaction_opts_set_read_concern(optionsPtr, rcPtr)
}
}
if let writeConcern = options?.writeConcern {
writeConcern.withMongocWriteConcern { wcPtr in
mongoc_transaction_opts_set_write_concern(optionsPtr, wcPtr)
}
}
if let rp = options?.readPreference {
rp.withMongocReadPreference { rpPtr in
mongoc_transaction_opts_set_read_prefs(optionsPtr, rpPtr)
}
}
if let maxCommitTimeMS = options?.maxCommitTimeMS {
mongoc_transaction_opts_set_max_commit_time_ms(optionsPtr, Int64(maxCommitTimeMS))
}
return try body(optionsPtr)
}
/// An operation corresponding to starting a transaction.
internal struct StartTransactionOperation: Operation {
/// The options to use when starting this transaction.
private let options: TransactionOptions?
internal init(options: TransactionOptions?) {
self.options = options
}
internal func execute(using _: Connection, session: ClientSession?) throws {
guard let session = session else {
throw MongoError.InternalError(message: "No session provided to StartTransactionOperation")
}
var error = bson_error_t()
let success = try session.withMongocSession { sessionPtr in
withMongocTransactionOpts(copying: self.options) { opts in
mongoc_client_session_start_transaction(sessionPtr, opts, &error)
}
}
guard success else {
throw extractMongoError(error: error)
}
}
}