@@ -10,7 +10,7 @@ use tokio::sync::RwLockReadGuard;
10
10
11
11
use crate :: {
12
12
bson:: { doc, Document } ,
13
- error:: Result ,
13
+ error:: { Result , TRANSIENT_TRANSACTION_ERROR , UNKNOWN_TRANSACTION_COMMIT_RESULT } ,
14
14
options:: {
15
15
Acknowledgment ,
16
16
ClientOptions ,
@@ -21,7 +21,7 @@ use crate::{
21
21
WriteConcern ,
22
22
} ,
23
23
runtime,
24
- sync:: { Client , Collection } ,
24
+ sync:: { Client , ClientSession , Collection } ,
25
25
test:: { TestClient as AsyncTestClient , LOCK } ,
26
26
} ;
27
27
@@ -243,6 +243,27 @@ fn transactions() {
243
243
return ;
244
244
}
245
245
246
+ fn run_transaction_with_retry (
247
+ session : & mut ClientSession ,
248
+ f : impl Fn ( & mut ClientSession ) -> Result < ( ) > ,
249
+ ) -> Result < ( ) > {
250
+ loop {
251
+ match f ( session) {
252
+ Ok ( ( ) ) => {
253
+ return Ok ( ( ) ) ;
254
+ }
255
+ Err ( error) => {
256
+ if error. contains_label ( TRANSIENT_TRANSACTION_ERROR ) {
257
+ continue ;
258
+ } else {
259
+ session. abort_transaction ( ) ?;
260
+ return Err ( error) ;
261
+ }
262
+ }
263
+ }
264
+ }
265
+ }
266
+
246
267
let options = CLIENT_OPTIONS . clone ( ) ;
247
268
let client = Client :: with_options ( options) . expect ( "client creation should succeed" ) ;
248
269
let mut session = client
@@ -258,17 +279,36 @@ fn transactions() {
258
279
session
259
280
. start_transaction ( None )
260
281
. expect ( "start transaction should succeed" ) ;
261
- coll. insert_one_with_session ( doc ! { "x" : 1 } , None , & mut session)
262
- . expect ( "insert should succeed" ) ;
263
- session
264
- . commit_transaction ( )
265
- . expect ( "commit transaction should succeed" ) ;
282
+
283
+ run_transaction_with_retry ( & mut session, |s| {
284
+ coll. insert_one_with_session ( doc ! { "x" : 1 } , None , s) ?;
285
+ Ok ( ( ) )
286
+ } )
287
+ . unwrap ( ) ;
288
+
289
+ loop {
290
+ match session. commit_transaction ( ) {
291
+ Ok ( ( ) ) => {
292
+ break ;
293
+ }
294
+ Err ( error) => {
295
+ if error. contains_label ( UNKNOWN_TRANSACTION_COMMIT_RESULT ) {
296
+ continue ;
297
+ } else {
298
+ panic ! ( "error while committing: {}" , error) ;
299
+ }
300
+ }
301
+ }
302
+ }
266
303
267
304
session
268
305
. start_transaction ( None )
269
306
. expect ( "start transaction should succeed" ) ;
270
- coll. insert_one_with_session ( doc ! { "x" : 1 } , None , & mut session)
271
- . expect ( "insert should succeed" ) ;
307
+ run_transaction_with_retry ( & mut session, |s| {
308
+ coll. insert_one_with_session ( doc ! { "x" : 1 } , None , s) ?;
309
+ Ok ( ( ) )
310
+ } )
311
+ . unwrap ( ) ;
272
312
session
273
313
. abort_transaction ( )
274
314
. expect ( "abort transaction should succeed" ) ;
0 commit comments