@@ -131,6 +131,40 @@ void putShouldSucceedWhenNoGlobalVersionIsGiven() {
131
131
assertThat (getObject (KVStore .GLOBAL_VERSION_KEY ).getVersion (), is (0L ));
132
132
}
133
133
134
+ @ Test
135
+ void putAndDeleteShouldSucceedAsAtomicTransaction () {
136
+ assertDoesNotThrow (() -> putObjects (null , List .of (kv ("k1" , "k1v1" , 0 ))));
137
+ // Put and Delete succeeds
138
+ assertDoesNotThrow (() -> putAndDeleteObjects (null , List .of (kv ("k2" , "k2v1" , 0 )), List .of (kv ("k1" , "" , 1 ))));
139
+
140
+ KeyValue response = getObject ("k2" );
141
+ assertThat (response .getKey (), is ("k2" ));
142
+ assertThat (response .getVersion (), is (1L ));
143
+ assertThat (response .getValue ().toStringUtf8 (), is ("k2v1" ));
144
+
145
+ assertTrue (getObject ("k1" ).getValue ().isEmpty ());
146
+
147
+ // Delete fails (and hence put as well) due to mismatched version for the deleted item.
148
+ assertThrows (ConflictException .class , () -> putAndDeleteObjects (null , List .of (kv ("k3" , "k3v1" , 0 )), List .of (kv ("k2" , "" , 3 ))));
149
+
150
+ assertTrue (getObject ("k3" ).getValue ().isEmpty ());
151
+ assertFalse (getObject ("k2" ).getValue ().isEmpty ());
152
+
153
+ // Put fails (and hence delete as well) due to mismatched version for the put item.
154
+ assertThrows (ConflictException .class , () -> putAndDeleteObjects (null , List .of (kv ("k3" , "k3v1" , 1 )), List .of (kv ("k2" , "" , 1 ))));
155
+
156
+ assertTrue (getObject ("k3" ).getValue ().isEmpty ());
157
+ assertFalse (getObject ("k2" ).getValue ().isEmpty ());
158
+
159
+ // Put and delete both fail due to mismatched global version.
160
+ assertThrows (ConflictException .class , () -> putAndDeleteObjects (2L , List .of (kv ("k3" , "k3v1" , 0 )), List .of (kv ("k2" , "" , 1 ))));
161
+
162
+ assertTrue (getObject ("k3" ).getValue ().isEmpty ());
163
+ assertFalse (getObject ("k2" ).getValue ().isEmpty ());
164
+
165
+ assertThat (getObject (KVStore .GLOBAL_VERSION_KEY ).getVersion (), is (0L ));
166
+ }
167
+
134
168
@ Test
135
169
void getShouldReturnEmptyResponseWhenKeyDoesNotExist () {
136
170
KeyValue response = getObject ("non_existent_key" );
@@ -370,6 +404,19 @@ private void putObjects(@Nullable Long globalVersion, List<KeyValue> keyValues)
370
404
this .kvStore .put (putObjectRequestBuilder .build ());
371
405
}
372
406
407
+ private void putAndDeleteObjects (@ Nullable Long globalVersion , List <KeyValue > putKeyValues , List <KeyValue > deleteKeyValues ) {
408
+ PutObjectRequest .Builder putObjectRequestBuilder = PutObjectRequest .newBuilder ()
409
+ .setStoreId (STORE_ID )
410
+ .addAllTransactionItems (putKeyValues )
411
+ .addAllDeleteItems (deleteKeyValues );
412
+
413
+ if (Objects .nonNull (globalVersion )) {
414
+ putObjectRequestBuilder .setGlobalVersion (globalVersion );
415
+ }
416
+
417
+ this .kvStore .put (putObjectRequestBuilder .build ());
418
+ }
419
+
373
420
private ListKeyVersionsResponse list (@ Nullable String nextPageToken , @ Nullable Integer pageSize ,
374
421
@ Nullable String keyPrefix ) {
375
422
ListKeyVersionsRequest .Builder listRequestBuilder = ListKeyVersionsRequest .newBuilder ()
0 commit comments