@@ -21,8 +21,9 @@ use rand::seq::IteratorRandom;
2121use rand:: thread_rng;
2222use rand:: Rng ;
2323use serial_test:: serial;
24+ use tikv_client:: backoff:: DEFAULT_REGION_BACKOFF ;
25+ use tikv_client:: proto:: kvrpcpb;
2426use tikv_client:: transaction:: HeartbeatOption ;
25- use tikv_client:: BoundRange ;
2627use tikv_client:: Error ;
2728use tikv_client:: Key ;
2829use tikv_client:: KvPair ;
@@ -31,6 +32,7 @@ use tikv_client::Result;
3132use tikv_client:: TransactionClient ;
3233use tikv_client:: TransactionOptions ;
3334use tikv_client:: Value ;
35+ use tikv_client:: { Backoff , BoundRange , RetryOptions , Transaction } ;
3436
3537// Parameters used in test
3638const NUM_PEOPLE : u32 = 100 ;
@@ -1078,3 +1080,123 @@ async fn txn_key_exists() -> Result<()> {
10781080 t3. commit ( ) . await ?;
10791081 Ok ( ( ) )
10801082}
1083+
1084+ #[ tokio:: test]
1085+ #[ serial]
1086+ async fn txn_batch_mutate_optimistic ( ) -> Result < ( ) > {
1087+ init ( ) . await ?;
1088+ let client = TransactionClient :: new ( pd_addrs ( ) ) . await ?;
1089+
1090+ // Put k0
1091+ {
1092+ let mut txn = client. begin_optimistic ( ) . await ?;
1093+ txn. put ( b"k0" . to_vec ( ) , b"v0" . to_vec ( ) ) . await ?;
1094+ txn. commit ( ) . await ?;
1095+ }
1096+ // Delete k0 and put k1, k2
1097+ do_mutate ( false ) . await . unwrap ( ) ;
1098+ // Read and verify
1099+ verify_mutate ( false ) . await ;
1100+ Ok ( ( ) )
1101+ }
1102+
1103+ #[ tokio:: test]
1104+ #[ serial]
1105+ async fn txn_batch_mutate_pessimistic ( ) -> Result < ( ) > {
1106+ init ( ) . await ?;
1107+ let client = TransactionClient :: new ( pd_addrs ( ) ) . await ?;
1108+
1109+ // Put k0
1110+ {
1111+ let mut txn = client. begin_pessimistic ( ) . await ?;
1112+ txn. put ( b"k0" . to_vec ( ) , b"v0" . to_vec ( ) ) . await ?;
1113+ txn. commit ( ) . await ?;
1114+ }
1115+ // txn1 lock k0, to verify pessimistic locking.
1116+ let mut txn1 = client. begin_pessimistic ( ) . await ?;
1117+ txn1. put ( b"k0" . to_vec ( ) , b"vv" . to_vec ( ) ) . await ?;
1118+
1119+ // txn2 is blocked by txn1, then timeout.
1120+ let txn2_handle = tokio:: spawn ( do_mutate ( true ) ) ;
1121+ assert ! ( matches!(
1122+ txn2_handle. await ?. unwrap_err( ) ,
1123+ Error :: PessimisticLockError { .. }
1124+ ) ) ;
1125+
1126+ let txn3_handle = tokio:: spawn ( do_mutate ( true ) ) ;
1127+ // txn1 rollback to release lock.
1128+ txn1. rollback ( ) . await ?;
1129+ txn3_handle. await ?. unwrap ( ) ;
1130+
1131+ // Read and verify
1132+ verify_mutate ( true ) . await ;
1133+ Ok ( ( ) )
1134+ }
1135+
1136+ async fn begin_mutate ( client : & TransactionClient , is_pessimistic : bool ) -> Result < Transaction > {
1137+ if is_pessimistic {
1138+ let options = TransactionOptions :: new_pessimistic ( ) . retry_options ( RetryOptions {
1139+ region_backoff : DEFAULT_REGION_BACKOFF ,
1140+ lock_backoff : Backoff :: no_jitter_backoff ( 500 , 500 , 2 ) ,
1141+ } ) ;
1142+ client. begin_with_options ( options) . await
1143+ } else {
1144+ client. begin_optimistic ( ) . await
1145+ }
1146+ }
1147+
1148+ async fn do_mutate ( is_pessimistic : bool ) -> Result < ( ) > {
1149+ let client = TransactionClient :: new ( pd_addrs ( ) ) . await . unwrap ( ) ;
1150+ let mut txn = begin_mutate ( & client, is_pessimistic) . await . unwrap ( ) ;
1151+
1152+ let mutations = vec ! [
1153+ kvrpcpb:: Mutation {
1154+ op: kvrpcpb:: Op :: Del . into( ) ,
1155+ key: b"k0" . to_vec( ) ,
1156+ ..Default :: default ( )
1157+ } ,
1158+ kvrpcpb:: Mutation {
1159+ op: kvrpcpb:: Op :: Put . into( ) ,
1160+ key: b"k1" . to_vec( ) ,
1161+ value: b"v1" . to_vec( ) ,
1162+ ..Default :: default ( )
1163+ } ,
1164+ kvrpcpb:: Mutation {
1165+ op: kvrpcpb:: Op :: Put . into( ) ,
1166+ key: b"k2" . to_vec( ) ,
1167+ value: b"v2" . to_vec( ) ,
1168+ ..Default :: default ( )
1169+ } ,
1170+ ] ;
1171+
1172+ match txn. batch_mutate ( mutations) . await {
1173+ Ok ( ( ) ) => {
1174+ txn. commit ( ) . await ?;
1175+ Ok ( ( ) )
1176+ }
1177+ Err ( err) => {
1178+ let _ = txn. rollback ( ) . await ;
1179+ Err ( err)
1180+ }
1181+ }
1182+ }
1183+
1184+ async fn verify_mutate ( is_pessimistic : bool ) {
1185+ let client = TransactionClient :: new ( pd_addrs ( ) ) . await . unwrap ( ) ;
1186+ let mut snapshot = snapshot ( & client, is_pessimistic) . await . unwrap ( ) ;
1187+ let res: HashMap < Key , Value > = snapshot
1188+ . batch_get ( vec ! [ "k0" . to_owned( ) , "k1" . to_owned( ) , "k2" . to_owned( ) ] )
1189+ . await
1190+ . unwrap ( )
1191+ . map ( |pair| ( pair. 0 , pair. 1 ) )
1192+ . collect ( ) ;
1193+ assert_eq ! ( res. len( ) , 2 ) ;
1194+ assert_eq ! (
1195+ res. get( & Key :: from( "k1" . to_owned( ) ) ) ,
1196+ Some ( Value :: from( "v1" . to_owned( ) ) ) . as_ref( )
1197+ ) ;
1198+ assert_eq ! (
1199+ res. get( & Key :: from( "k2" . to_owned( ) ) ) ,
1200+ Some ( Value :: from( "v2" . to_owned( ) ) ) . as_ref( )
1201+ ) ;
1202+ }
0 commit comments