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