@@ -19,6 +19,8 @@ fn test_get() {
1919 futures:: executor:: block_on ( test_set_conflict_async ( ) ) . expect ( "failed to run" ) ;
2020 futures:: executor:: block_on ( test_set_conflict_snapshot_async ( ) ) . expect ( "failed to run" ) ;
2121 futures:: executor:: block_on ( test_transact_async ( ) ) . expect ( "failed to run" ) ;
22+ futures:: executor:: block_on ( test_transact_limit ( ) ) . expect ( "failed to run" ) ;
23+ futures:: executor:: block_on ( test_transact_timeout ( ) ) . expect ( "failed to run" ) ;
2224 futures:: executor:: block_on ( test_versionstamp_async ( ) ) . expect ( "failed to run" ) ;
2325 futures:: executor:: block_on ( test_read_version_async ( ) ) . expect ( "failed to run" ) ;
2426 futures:: executor:: block_on ( test_set_read_version_async ( ) ) . expect ( "failed to run" ) ;
@@ -167,6 +169,86 @@ async fn test_transact_async() -> FdbResult<()> {
167169 Ok ( ( ) )
168170}
169171
172+ async fn test_transact_limit ( ) -> FdbResult < ( ) > {
173+ const KEY : & [ u8 ] = b"test_transact_limit" ;
174+ async fn async_body (
175+ db : & Database ,
176+ trx : & Transaction ,
177+ try_count0 : Arc < AtomicUsize > ,
178+ ) -> FdbResult < ( ) > {
179+ // increment try counter
180+ try_count0. fetch_add ( 1 , Ordering :: SeqCst ) ;
181+
182+ // update conflict range
183+ trx. get ( KEY , false ) . await ?;
184+
185+ // make current transaction invalid by making conflict
186+ make_dirty ( & db, KEY ) . await ?;
187+
188+ trx. set ( KEY , common:: random_str ( 10 ) . as_bytes ( ) ) ;
189+
190+ // `Database::transact` will handle commit by itself, so returns without commit
191+ Ok ( ( ) )
192+ }
193+
194+ let try_count = Arc :: new ( AtomicUsize :: new ( 0 ) ) ;
195+ let db = common:: database ( ) . await ?;
196+ let res = db
197+ . transact_boxed (
198+ & db,
199+ |trx, db| async_body ( db, trx, try_count. clone ( ) ) . boxed ( ) ,
200+ TransactOption {
201+ retry_limit : Some ( 5 ) ,
202+ ..TransactOption :: default ( )
203+ } ,
204+ )
205+ . await ;
206+ assert ! ( res. is_err( ) , "should not be able to commit" ) ;
207+
208+ assert_eq ! ( try_count. load( Ordering :: SeqCst ) , 5 ) ;
209+
210+ Ok ( ( ) )
211+ }
212+
213+ async fn test_transact_timeout ( ) -> FdbResult < ( ) > {
214+ const KEY : & [ u8 ] = b"test_transact_timeout" ;
215+ async fn async_body (
216+ db : & Database ,
217+ trx : & Transaction ,
218+ try_count0 : Arc < AtomicUsize > ,
219+ ) -> FdbResult < ( ) > {
220+ // increment try counter
221+ try_count0. fetch_add ( 1 , Ordering :: SeqCst ) ;
222+
223+ // update conflict range
224+ trx. get ( KEY , false ) . await ?;
225+
226+ // make current transaction invalid by making conflict
227+ make_dirty ( & db, KEY ) . await ?;
228+
229+ trx. set ( KEY , common:: random_str ( 10 ) . as_bytes ( ) ) ;
230+
231+ // `Database::transact` will handle commit by itself, so returns without commit
232+ Ok ( ( ) )
233+ }
234+
235+ let try_count = Arc :: new ( AtomicUsize :: new ( 0 ) ) ;
236+ let db = common:: database ( ) . await ?;
237+ let res = db
238+ . transact_boxed (
239+ & db,
240+ |trx, db| async_body ( db, trx, try_count. clone ( ) ) . boxed ( ) ,
241+ TransactOption {
242+ time_out : Some ( std:: time:: Duration :: from_millis ( 250 ) ) ,
243+ ..TransactOption :: default ( )
244+ } ,
245+ )
246+ . await ;
247+ assert ! ( res. is_err( ) , "should not be able to commit" ) ;
248+
249+ Ok ( ( ) )
250+ }
251+
170252async fn test_versionstamp_async ( ) -> FdbResult < ( ) > {
171253 const KEY : & [ u8 ] = b"test_versionstamp" ;
172254 let db = common:: database ( ) . await ?;
0 commit comments