Skip to content

Commit e15db9b

Browse files
committed
Add Delete functionality
1 parent 909f7cc commit e15db9b

File tree

2 files changed

+74
-9
lines changed

2 files changed

+74
-9
lines changed

app/src/main/java/org/vss/impl/postgres/PostgresBackendImpl.java

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,23 +66,31 @@ public PutObjectResponse put(PutObjectRequest request) {
6666

6767
String storeId = request.getStoreId();
6868

69-
List<VssDbRecord> vssRecords = new ArrayList<>(request.getTransactionItemsList().stream()
69+
List<VssDbRecord> vssPutRecords = new ArrayList<>(request.getTransactionItemsList().stream()
70+
.map(kv -> buildVssRecord(storeId, kv)).toList());
71+
72+
List<VssDbRecord> vssDeleteRecords = new ArrayList<>(request.getDeleteItemsList().stream()
7073
.map(kv -> buildVssRecord(storeId, kv)).toList());
7174

7275
if (request.hasGlobalVersion()) {
7376
VssDbRecord globalVersionRecord = buildVssRecord(storeId,
7477
KeyValue.newBuilder()
7578
.setKey(GLOBAL_VERSION_KEY)
7679
.setVersion(request.getGlobalVersion())
80+
.setValue(ByteString.EMPTY)
7781
.build());
7882

79-
vssRecords.add(globalVersionRecord);
83+
vssPutRecords.add(globalVersionRecord);
8084
}
8185

8286
context.transaction((ctx) -> {
8387
DSLContext dsl = ctx.dsl();
84-
List<Query> batchQueries = vssRecords.stream()
85-
.map(vssRecord -> buildPutObjectQuery(dsl, vssRecord)).toList();
88+
List<Query> batchQueries = new ArrayList<>();
89+
90+
batchQueries.addAll(vssPutRecords.stream()
91+
.map(vssRecord -> buildPutObjectQuery(dsl, vssRecord)).toList());
92+
batchQueries.addAll(vssDeleteRecords.stream()
93+
.map(vssRecord -> buildDeleteObjectQuery(dsl, vssRecord)).toList());
8694

8795
int[] batchResult = dsl.batch(batchQueries).execute();
8896

@@ -97,6 +105,12 @@ public PutObjectResponse put(PutObjectRequest request) {
97105
return PutObjectResponse.newBuilder().build();
98106
}
99107

108+
private Query buildDeleteObjectQuery(DSLContext dsl, VssDbRecord vssRecord) {
109+
return dsl.deleteFrom(VSS_DB).where(VSS_DB.STORE_ID.eq(vssRecord.getStoreId())
110+
.and(VSS_DB.KEY.eq(vssRecord.getKey()))
111+
.and(VSS_DB.VERSION.eq(vssRecord.getVersion())));
112+
}
113+
100114
private Query buildPutObjectQuery(DSLContext dsl, VssDbRecord vssRecord) {
101115
return vssRecord.getVersion() == 0 ? buildInsertRecordQuery(dsl, vssRecord)
102116
: buildUpdateRecordQuery(dsl, vssRecord);
@@ -122,8 +136,8 @@ private VssDbRecord buildVssRecord(String storeId, KeyValue kv) {
122136
return new VssDbRecord()
123137
.setStoreId(storeId)
124138
.setKey(kv.getKey())
125-
.setValue(kv.getValue().toByteArray())
126-
.setVersion(kv.getVersion());
139+
.setVersion(kv.getVersion())
140+
.setValue(kv.getValue().toByteArray());
127141
}
128142

129143
@Override

app/src/main/proto/vss.proto

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
syntax = "proto3";
2+
package vss;
23
option java_multiple_files = true;
3-
package org.vss;
4+
option java_package = "org.vss";
45

6+
// Request payload to be used for `GetObject` API call to server.
57
message GetObjectRequest {
68

79
// store_id is a keyspace identifier.
@@ -24,12 +26,14 @@ message GetObjectRequest {
2426
string key = 2;
2527
}
2628

29+
// Server response for `GetObject` API.
2730
message GetObjectResponse {
2831

2932
// Fetched value and version along with the corresponding key in the request.
3033
KeyValue value = 2;
3134
}
3235

36+
// Request payload to be used for `PutObject` API call to server.
3337
message PutObjectRequest {
3438

3539
// store_id is a keyspace identifier.
@@ -65,9 +69,9 @@ message PutObjectRequest {
6569
// Clients can choose to encrypt the keys client-side in order to obfuscate their usage patterns.
6670
// If the write is successful, the previous value corresponding to the key will be overwritten.
6771
//
68-
// Multiple items in transaction_items of a single PutObjectRequest are written in
72+
// Multiple items in transaction_items and delete_items of a single PutObjectRequest are written in
6973
// a database-transaction in an all-or-nothing fashion.
70-
// Items in a single PutObjectRequest must have distinct keys.
74+
// All Items in a single PutObjectRequest must have distinct keys.
7175
//
7276
// Clients are expected to store a version against every key.
7377
// The write will succeed if the current DB version against the key is the same as in the request.
@@ -93,11 +97,56 @@ message PutObjectRequest {
9397
// All PutObjectRequests are strongly consistent i.e. they provide read-after-write and
9498
// read-after-update consistency guarantees.
9599
repeated KeyValue transaction_items = 3;
100+
101+
// Items to be deleted as a result of this PutObjectRequest.
102+
//
103+
// Each item in the `delete_items` field consists of a key and its corresponding version.
104+
// The version is used to perform a version check before deleting the item.
105+
// The delete will only succeed if the current database version against the key is the same as the version
106+
// specified in the request.
107+
//
108+
// Fails with `CONFLICT_EXCEPTION` as ErrorCode if :
109+
// * The requested item does not exist.
110+
// * The requested item does exist but there is a version-number mismatch with the one in DB.
111+
//
112+
// Multiple items in the `delete_items` field, along with the `transaction_items`, are written in a
113+
// database transaction in an all-or-nothing fashion.
114+
//
115+
// All items within a single `PutObjectRequest` must have distinct keys.
116+
repeated KeyValue delete_items = 4;
96117
}
97118

119+
// Server response for `PutObject` API.
98120
message PutObjectResponse {
99121
}
100122

123+
// Request payload to be used for `DeleteObject` API call to server.
124+
message DeleteObjectRequest {
125+
// store_id is a keyspace identifier.
126+
// Ref: https://en.wikipedia.org/wiki/Keyspace_(distributed_data_store)
127+
// All APIs operate within a single store_id.
128+
// It is up to clients to use single or multiple stores for their use-case.
129+
// This can be used for client-isolation/ rate-limiting / throttling on the server-side.
130+
// Authorization and billing can also be performed at the store_id level.
131+
string store_id = 1;
132+
133+
// Item to be deleted as a result of this DeleteObjectRequest.
134+
//
135+
// An item consists of a key and its corresponding version.
136+
// The item is only deleted if the current database version against the key is the same as the version
137+
// specified in the request.
138+
// This operation is idempotent, that is, multiple delete calls for the same item will not fail.
139+
//
140+
// If the requested item does not exist, this operation will not fail.
141+
// If you wish to perform stricter checks while deleting an item, consider using PutObject API.
142+
KeyValue key_value = 2;
143+
}
144+
145+
// Server response for `DeleteObject` API.
146+
message DeleteObjectResponse{
147+
}
148+
149+
// Request payload to be used for `ListKeyVersions` API call to server.
101150
message ListKeyVersionsRequest {
102151

103152
// store_id is a keyspace identifier.
@@ -133,6 +182,7 @@ message ListKeyVersionsRequest {
133182
optional string page_token = 4;
134183
}
135184

185+
// Server response for `ListKeyVersions` API.
136186
message ListKeyVersionsResponse {
137187

138188
// Fetched keys and versions.
@@ -206,6 +256,7 @@ enum ErrorCode {
206256
INTERNAL_SERVER_EXCEPTION = 3;
207257
}
208258

259+
// Represents KeyValue pair to be stored or retrieved.
209260
message KeyValue {
210261

211262
// Key against which the value is stored.

0 commit comments

Comments
 (0)