@@ -147,3 +147,81 @@ private func changeStreams() throws {
147147 // End Changestream Example 4
148148 }
149149}
150+
151+ /// Examples used for the MongoDB documentation on transactions.
152+ /// - SeeAlso: https://docs.mongodb.com/manual/core/transactions-in-applications/
153+ private func transactions( ) throws {
154+ let elg = MultiThreadedEventLoopGroup ( numberOfThreads: 1 )
155+ let client = try MongoClient ( using: elg)
156+
157+ // Start Transactions Into Example 1
158+ func updateEmployeeInfo( session: ClientSession ) -> EventLoopFuture < Void > {
159+ let employees = client. db ( " hr " ) . collection ( " employees " )
160+ let events = client. db ( " reporting " ) . collection ( " events " )
161+
162+ let options = TransactionOptions ( readConcern: . snapshot, writeConcern: . majority)
163+ return session. startTransaction ( options: options) . flatMap {
164+ employees. updateOne (
165+ filter: [ " employee " : 3 ] ,
166+ update: [ " $set " : [ " status " : " Inactive " ] ] ,
167+ session: session
168+ ) . flatMap { _ in
169+ events. insertOne ( [ " employee " : 3 , " status " : [ " new " : " Inactive " , " old " : " Active " ] ] )
170+ } . flatMapError { error in
171+ print ( " Caught error during transaction, aborting " )
172+ return session. abortTransaction ( ) . flatMapThrowing { _ in
173+ throw error
174+ }
175+ }
176+ } . flatMap { _ in
177+ commitWithRetry ( session: session)
178+ }
179+ }
180+ // End Transactions Intro Example 1
181+
182+ // Start Transactions Retry Example 1
183+ func runTransactionWithRetry(
184+ session: ClientSession ,
185+ txnFunc: @escaping ( ClientSession ) -> EventLoopFuture < Void >
186+ ) -> EventLoopFuture < Void > {
187+ let txnFuture = txnFunc ( session)
188+ let eventLoop = txnFuture. eventLoop
189+ return txnFuture. flatMapError { error in
190+ guard
191+ let labeledError = error as? LabeledError ,
192+ labeledError. errorLabels? . contains ( " TransientTransactionError " ) == true
193+ else {
194+ return eventLoop. makeFailedFuture ( error)
195+ }
196+ print ( " TransientTransactionError, retrying transaction... " )
197+ return runTransactionWithRetry ( session: session, txnFunc: txnFunc)
198+ }
199+ }
200+ // End Transactions Retry Example 1
201+
202+ // Start Transactions Retry Example 2
203+ func commitWithRetry( session: ClientSession ) -> EventLoopFuture < Void > {
204+ let commitFuture = session. commitTransaction ( )
205+ let eventLoop = commitFuture. eventLoop
206+ return commitFuture. flatMapError { error in
207+ guard
208+ let labeledError = error as? LabeledError ,
209+ labeledError. errorLabels? . contains ( " UnknownTransactionCommitResult " ) == true
210+ else {
211+ print ( " Error during commit... " )
212+ return eventLoop. makeFailedFuture ( error)
213+ }
214+ print ( " UnknownTransactionCommitResult, retrying commit operation... " )
215+ return commitWithRetry ( session: session)
216+ }
217+ }
218+ // End Transactions Retry Example 2
219+
220+ // Start Transactions Retry Example 3
221+ try client. withSession { session in
222+ runTransactionWithRetry ( session: session, txnFunc: updateEmployeeInfo) . flatMapErrorThrowing { _ in
223+ // do something with error
224+ }
225+ } . wait ( )
226+ // End Transactions Retry Example 3
227+ }
0 commit comments