Skip to content

Commit 7b9e187

Browse files
committed
Add Vss thin client protobuf generation & build setup
1 parent 3494efa commit 7b9e187

File tree

5 files changed

+253
-0
lines changed

5 files changed

+253
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/target

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[workspace]
2+
members = [
3+
"vss-accessor",
4+
]

vss-accessor/Cargo.toml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[package]
2+
name = "vss-accessor"
3+
version = "0.1.0"
4+
edition = "2021"
5+
build = "build.rs"
6+
7+
[dependencies]
8+
prost = "0.11.3"
9+
reqwest = "0.11.13"
10+
11+
[dev-dependencies]
12+
mockito = "0.31.1"
13+
tokio = { version = "1.22.0"}
14+
15+
[build-dependencies]
16+
prost-build = { version = "0.11.3" }

vss-accessor/build.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
extern crate prost_build;
2+
3+
fn main() {
4+
prost_build::compile_protos(&["src/proto/vss.proto"],
5+
&["src/"]).unwrap();
6+
}

vss-accessor/src/proto/vss.proto

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
syntax = "proto3";
2+
option java_multiple_files = true;
3+
package org.vss;
4+
5+
message GetObjectRequest {
6+
7+
// store_id is a keyspace identifier.
8+
// Ref: https://en.wikipedia.org/wiki/Keyspace_(distributed_data_store)
9+
// All APIs operate within a single store_id.
10+
// It is up to clients to use single or multiple stores for their use-case.
11+
// This can be used for client-isolation/ rate-limiting / throttling on the server-side.
12+
// Authorization and billing can also be performed at the store_id level.
13+
string store_id = 1;
14+
15+
// Key for which the value is to be fetched.
16+
//
17+
// Consistency Guarantee:
18+
// Get(read) operations against a key are consistent reads and will reflect all previous writes,
19+
// since Put/Write provides read-after-write and read-after-update consistency guarantees.
20+
//
21+
// Read Isolation:
22+
// Get/Read operations against a key are ensured to have read-committed isolation.
23+
// Ref: https://en.wikipedia.org/wiki/Isolation_(database_systems)#Read_committed
24+
string key = 2;
25+
}
26+
27+
message GetObjectResponse {
28+
29+
// Fetched value and version along with the corresponding key in the request.
30+
KeyValue value = 2;
31+
}
32+
33+
message PutObjectRequest {
34+
35+
// store_id is a keyspace identifier.
36+
// Ref: https://en.wikipedia.org/wiki/Keyspace_(distributed_data_store)
37+
// All APIs operate within a single store_id.
38+
// It is up to clients to use single or multiple stores for their use-case.
39+
// This can be used for client-isolation/ rate-limiting / throttling on the server-side.
40+
// Authorization and billing can also be performed at the store_id level.
41+
string store_id = 1;
42+
43+
// global_version is a sequence-number/version of the whole store. This can be used for versioning
44+
// and ensures that multiple updates in case of multiple devices can only be done linearly, even
45+
// if those updates did not directly conflict with each other based on keys/transaction_items.
46+
//
47+
// If present, the write will only succeed if the current server-side global_version against
48+
// the store_id is same as in the request.
49+
// Clients are expected to store (client-side) the global version against store_id.
50+
// The request must contain their client-side value of global_version if global versioning and
51+
// conflict detection is desired.
52+
//
53+
// For the first write of the store, global version should be '0'. If the write succeeds, clients
54+
// must increment their global version (client-side) by 1.
55+
// The server increments global_version (server-side) for every successful write, hence this
56+
// client-side increment is required to ensure matching versions. This updated global version
57+
// should be used in subsequent PutObjectRequests for the store.
58+
//
59+
// Requests with a conflicting version will fail with `CONFLICT_EXCEPTION` as ErrorCode.
60+
optional int64 global_version = 2;
61+
62+
// Items to be written as a result of this PutObjectRequest.
63+
//
64+
// In an item, each key is supplied with its corresponding value and version.
65+
// Clients can choose to encrypt the keys client-side in order to obfuscate their usage patterns.
66+
// If the write is successful, the previous value corresponding to the key will be overwritten.
67+
//
68+
// Multiple items in transaction_items of a single PutObjectRequest are written in
69+
// a database-transaction in an all-or-nothing fashion.
70+
// Items in a single PutObjectRequest must have distinct keys.
71+
//
72+
// Clients are expected to store a version against every key.
73+
// The write will succeed if the current DB version against the key is the same as in the request.
74+
// When initiating a PutObjectRequest, the request should contain their client-side version for
75+
// that key-value.
76+
//
77+
// For the first write of any key, the version should be '0'. If the write succeeds, the client
78+
// must increment their corresponding key versions (client-side) by 1.
79+
// The server increments key versions (server-side) for every successful write, hence this
80+
// client-side increment is required to ensure matching versions. These updated key versions should
81+
// be used in subsequent PutObjectRequests for the keys.
82+
//
83+
// Requests with a conflicting version will fail with `CONFLICT_EXCEPTION` as ErrorCode.
84+
//
85+
// Considerations for transactions:
86+
// Transaction writes of multiple items have a performance overhead, hence it is recommended to use
87+
// them only if required by the client application to ensure logic/code correctness.
88+
// That is, transaction_items are not a substitute for batch-write of multiple unrelated items.
89+
// When a write of multiple unrelated items is desired, it is recommended to use separate
90+
// PutObjectRequests.
91+
//
92+
// Consistency guarantee:
93+
// All PutObjectRequests are strongly consistent i.e. they provide read-after-write and
94+
// read-after-update consistency guarantees.
95+
repeated KeyValue transaction_items = 3;
96+
}
97+
98+
message PutObjectResponse {
99+
}
100+
101+
message ListKeyVersionsRequest {
102+
103+
// store_id is a keyspace identifier.
104+
// Ref: https://en.wikipedia.org/wiki/Keyspace_(distributed_data_store)
105+
// All APIs operate within a single store_id.
106+
// It is up to clients to use single or multiple stores for their use-case.
107+
// This can be used for client-isolation/ rate-limiting / throttling on the server-side.
108+
// Authorization and billing can also be performed at the store_id level.
109+
string store_id = 1;
110+
111+
// A key_prefix is a string of characters at the beginning of the key. Prefixes can be used as
112+
// a way to organize key-values in a similar way to directories.
113+
//
114+
// If key_prefix is specified, the response results will be limited to those keys that begin with
115+
// the specified prefix.
116+
//
117+
// If no key_prefix is specified or it is empty (""), all the keys are eligible to be returned in
118+
// the response.
119+
optional string key_prefix = 2;
120+
121+
// page_size is used by clients to specify the maximum number of results that can be returned by
122+
// the server.
123+
// The server may further constrain the maximum number of results returned in a single page.
124+
// If the page_size is 0 or not set, the server will decide the number of results to be returned.
125+
optional int32 page_size = 3;
126+
127+
// page_token is a pagination token.
128+
//
129+
// To query for the first page of ListKeyVersions, page_token must not be specified.
130+
//
131+
// For subsequent pages, use the value that was returned as `next_page_token` in the previous
132+
// page's ListKeyVersionsResponse.
133+
optional string page_token = 4;
134+
}
135+
136+
message ListKeyVersionsResponse {
137+
138+
// Fetched keys and versions.
139+
// Even though this API reuses KeyValue struct, the value sub-field will not be set by the server.
140+
repeated KeyValue key_versions = 1;
141+
142+
// next_page_token is a pagination token, used to retrieve the next page of results.
143+
// Use this value to query for next_page of paginated ListKeyVersions operation, by specifying
144+
// this value as the `page_token` in the next request.
145+
//
146+
// If next_page_token is empty (""), then the "last page" of results has been processed and
147+
// there is no more data to be retrieved.
148+
//
149+
// If next_page_token is not empty, it does not necessarily mean that there is more data in the
150+
// result set. The only way to know when you have reached the end of the result set is when
151+
// next_page_token is empty.
152+
//
153+
// Caution: Clients must not assume a specific number of key_versions to be present in a page for
154+
// paginated response.
155+
optional string next_page_token = 2;
156+
157+
// global_version is a sequence-number/version of the whole store.
158+
//
159+
// global_version is only returned in response for the first page of the ListKeyVersionsResponse
160+
// and is guaranteed to be read before reading any key-versions.
161+
//
162+
// In case of refreshing the complete key-version view on the client-side, correct usage for
163+
// the returned global_version is as following:
164+
// 1. Read global_version from the first page of paginated response and save it as local variable.
165+
// 2. Update all the key_versions on client-side from all the pages of paginated response.
166+
// 3. Update global_version on client_side from the local variable saved in step-1.
167+
// This ensures that on client-side, all current key_versions were stored at global_version or later.
168+
// This guarantee is helpful for ensuring the versioning correctness if using the global_version
169+
// in PutObject API and can help avoid the race conditions related to it.
170+
optional int64 global_version = 3;
171+
}
172+
173+
// When HttpStatusCode is not ok (200), the response `content` contains a serialized ErrorResponse
174+
// with the relevant ErrorCode and message
175+
message ErrorResponse {
176+
177+
// The error code uniquely identifying an error condition.
178+
// It is meant to be read and understood programmatically by code that detects/handles errors by
179+
// type.
180+
ErrorCode error_code = 1;
181+
182+
// The error message containing a generic description of the error condition in English.
183+
// It is intended for a human audience only and should not be parsed to extract any information
184+
// programmatically. Client-side code may use it for logging only.
185+
string message = 2;
186+
}
187+
188+
// ErrorCodes to be used in ErrorResponse
189+
enum ErrorCode {
190+
191+
// Default protobuf Enum value. Will not be used as ErrorCode by server.
192+
UNKNOWN = 0;
193+
194+
// CONFLICT_EXCEPTION is used when the request contains mismatched version (either key or global)
195+
// in PutObjectRequest. For more info refer PutObjectRequest.
196+
CONFLICT_EXCEPTION= 1;
197+
198+
// INVALID_REQUEST_EXCEPTION is used in the following cases:
199+
// - The request was missing a required argument.
200+
// - The specified argument was invalid, incomplete or in the wrong format.
201+
// - The request body of api cannot be deserialized into corresponding protobuf object.
202+
INVALID_REQUEST_EXCEPTION = 2;
203+
204+
// An internal server error occurred, client is probably at no fault and can safely retry this
205+
// error with exponential backoff.
206+
INTERNAL_SERVER_EXCEPTION = 3;
207+
}
208+
209+
message KeyValue {
210+
211+
// Key against which the value is stored.
212+
string key = 1;
213+
214+
// Version field is used for key-level versioning.
215+
// For first write of key, version should be '0'. If the write succeeds, clients must increment
216+
// their corresponding key version (client-side) by 1.
217+
// The server increments key version (server-side) for every successful write, hence this
218+
// client-side increment is required to ensure matching versions. These updated key versions should
219+
// be used in subsequent PutObjectRequests for the keys.
220+
int64 version = 2;
221+
222+
// Object value in bytes which is stored (in put) and fetched (in get).
223+
// Clients must encrypt this blob client-side before sending it over the wire to server in order
224+
// to preserve privacy and security.
225+
bytes value = 3;
226+
}

0 commit comments

Comments
 (0)