Skip to content

Commit a232d6c

Browse files
Merge pull request #425 from skyflowapi/SK-3131-unary-operations-in-java-flowvault-sdk
SK-3131 Added unary operations
2 parents 442ad85 + e87efb3 commit a232d6c

19 files changed

Lines changed: 224 additions & 207 deletions

File tree

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,11 @@
11
package com.skyflow.vault.data;
22

3-
import java.util.ArrayList;
4-
53
public class BaseGetRequest {
6-
private final BaseGetRequestBuilder builder;
7-
84
protected BaseGetRequest(BaseGetRequestBuilder builder) {
9-
this.builder = builder;
10-
}
11-
12-
public String getTable() {
13-
return this.builder.table;
14-
}
15-
16-
public ArrayList<String> getIds() {
17-
return this.builder.ids;
18-
}
19-
20-
public ArrayList<String> getFields() {
21-
return this.builder.fields;
225
}
236

247
static class BaseGetRequestBuilder {
25-
protected String table;
26-
protected ArrayList<String> ids;
27-
protected ArrayList<String> fields;
28-
298
protected BaseGetRequestBuilder() {
309
}
31-
32-
public BaseGetRequestBuilder table(String table) {
33-
this.table = table;
34-
return this;
35-
}
36-
37-
public BaseGetRequestBuilder ids(ArrayList<String> ids) {
38-
this.ids = ids;
39-
return this;
40-
}
41-
42-
public BaseGetRequestBuilder fields(ArrayList<String> fields) {
43-
this.fields = fields;
44-
return this;
45-
}
4610
}
4711
}

flowvault/README.md

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ This reflects supported use cases, not something the SDK validates or blocks —
325325

326326
Each method also accepts an optional options object (`BulkInsertOptions`, `BulkTokenizeOptions`, `BulkDetokenizeOptions`, `BulkDeleteTokensOptions`) — see [Custom Request Headers](#custom-request-headers).
327327

328-
A single bulk call accepts at most **10,000** records or tokens; anything larger is rejected up front with a `SkyflowException`. Under that ceiling the SDK splits the payload into batches and sends them concurrently, which is why errors from one call can carry different `requestId` values.
328+
A single bulk call accepts at most **100,000** records or tokens; anything larger is rejected up front with a `SkyflowException`. Under that ceiling the SDK splits the payload into batches and sends them concurrently, which is why errors from one call can carry different `requestId` values.
329329

330330
Every bulk response has the same two-part shape:
331331

@@ -340,10 +340,10 @@ Batch size and concurrency are configured **per operation** through environment
340340

341341
| Operation | Batch size variable | Default | Max | Concurrency variable | Default | Max |
342342
|-----------|--------------------|---------|-----|---------------------|---------|-----|
343-
| Bulk insert | `INSERT_BATCH_SIZE` | 50 | 1000 | `INSERT_CONCURRENCY_LIMIT` | 1 | 10 |
344-
| Bulk tokenize | `TOKENIZE_BATCH_SIZE` | 50 | 1000 | `TOKENIZE_CONCURRENCY_LIMIT` | 1 | 10 |
345-
| Bulk detokenize | `DETOKENIZE_BATCH_SIZE` | 50 | 1000 | `DETOKENIZE_CONCURRENCY_LIMIT` | 1 | 10 |
346-
| Bulk delete tokens | `DELETE_TOKENS_BATCH_SIZE` | 50 | 1000 | `DELETE_TOKENS_CONCURRENCY_LIMIT` | 1 | 10 |
343+
| Bulk insert | `INSERT_BATCH_SIZE` | 50 | 1000 | `INSERT_CONCURRENCY_LIMIT` | 1 | 100 |
344+
| Bulk tokenize | `TOKENIZE_BATCH_SIZE` | 50 | 1000 | `TOKENIZE_CONCURRENCY_LIMIT` | 1 | 100 |
345+
| Bulk detokenize | `DETOKENIZE_BATCH_SIZE` | 50 | 1000 | `DETOKENIZE_CONCURRENCY_LIMIT` | 1 | 100 |
346+
| Bulk delete tokens | `DELETE_TOKENS_BATCH_SIZE` | 50 | 1000 | `DELETE_TOKENS_CONCURRENCY_LIMIT` | 1 | 100 |
347347

348348
Concurrency defaults to **1**, so batches are sent one after another unless you raise the limit.
349349

@@ -362,7 +362,7 @@ INSERT_BATCH_SIZE=100
362362
INSERT_CONCURRENCY_LIMIT=5
363363
```
364364

365-
The 10,000-item ceiling per bulk call is a separate, fixed limit and is not configurable.
365+
The 100,000-item ceiling per bulk call is a separate, fixed limit and is not configurable.
366366

367367
# VaultController — Unary operations
368368

@@ -389,7 +389,7 @@ Everything the bulk machinery adds — batching, concurrency, the payload ceilin
389389
|---|---|---|
390390
| Async variant | Yes — `bulkInsertAsync`, and so on | **No.** Wrap the call yourself if you need one |
391391
| Batching and concurrency | Configured per operation — see [Batching and concurrency](#batching-and-concurrency) | Not applicable — one payload, one call |
392-
| Payload ceiling | 10,000 records or tokens per call | Not enforced by the SDK; the vault's own request limits still apply |
392+
| Payload ceiling | 100,000 records or tokens per call | Not enforced by the SDK; the vault's own request limits still apply |
393393
| Response summary | `getSummary()` | None — read the records list |
394394
| Per-item `getIndex()` / `getRequestId()` | Yes | No. Records come back in submitted order, and the `x-request-id` of the single call reaches you only through a thrown `SkyflowException` |
395395
| Retry helper | `getRecordsToRetry()` / `getTokensToRetry()` | None — filter the records yourself, see [Retrying the failed records](#retrying-the-failed-records) |
@@ -990,10 +990,10 @@ Read records back from a table, by skyflow ID or by unique value, optionally ove
990990
991991
**Note:**
992992

993-
- A `GetRequest` works in one of two modes, and they are mutually exclusive: **single-table** (`table`, `ids`/`uniqueValues`, `fields`, `columnRedactions`, `limit`, `offset`) or **multi-table** (`records`, a list of `GetRequestRecord`). Setting fields from both modes fails validation.
994-
- `table` is required, and exactly one of `ids` or `uniqueValues` must be supplied — both, or neither, fails validation. This holds per record in multi-table mode.
993+
- A `GetRequest` works in one of two modes, and they are mutually exclusive: **single-table** (`tableName`, `skyflowIds`/`uniqueValues`, `columns`, `columnRedactions`, `limit`, `offset`) or **multi-table** (`records`, a list of `GetRequestRecord`). Setting fields from both modes fails validation.
994+
- `tableName` is required, and exactly one of `skyflowIds` or `uniqueValues` must be supplied — both, or neither, fails validation. This holds per record in multi-table mode.
995995
- `uniqueValues` is a `List<Map<String, Object>>`: one map per record, each holding the unique column-name/value pairs that identify it.
996-
- `fields` selects the columns to return; omit it for all of them. When supplied, it must be non-empty with no blank entries.
996+
- `columns` selects the columns to return; omit it for all of them. When supplied, it must be non-empty with no blank entries.
997997
- `limit` and `offset` apply to the call as a whole and are **only sent in single-table mode** — a `GetRequestRecord` has no `limit`/`offset` of its own, and values set on a multi-table request are not sent.
998998

999999
### Construct a get request
@@ -1020,11 +1020,11 @@ public class GetExample {
10201020

10211021
// Step 2: Build the GetRequest — single-table mode, selecting records by skyflow ID
10221022
GetRequest getRequest = GetRequest.builder()
1023-
.table("table1")
1024-
.ids(new ArrayList<>(Arrays.asList(
1023+
.tableName("table1")
1024+
.skyflowIds(new ArrayList<>(Arrays.asList(
10251025
"9fac9201-7b8a-4446-93f8-5244e1213bd1",
10261026
"b2308e2a-c1f5-469b-97b7-1f193159399b")))
1027-
.fields(new ArrayList<>(Arrays.asList("card_number", "cardholder_name")))
1027+
.columns(new ArrayList<>(Arrays.asList("card_number", "cardholder_name")))
10281028
.columnRedactions(Collections.singletonList(redaction))
10291029
.limit(10)
10301030
.offset(0)
@@ -1037,14 +1037,14 @@ public class GetExample {
10371037
}
10381038
```
10391039

1040-
To select records by unique value instead of skyflow ID, swap `ids(...)` for `uniqueValues(...)`:
1040+
To select records by unique value instead of skyflow ID, swap `skyflowIds(...)` for `uniqueValues(...)`:
10411041

10421042
```java
10431043
Map<String, Object> uniqueValue = new HashMap<>();
10441044
uniqueValue.put("email", "jane.doe@example.com");
10451045

10461046
GetRequest getRequest = GetRequest.builder()
1047-
.table("table2")
1047+
.tableName("table2")
10481048
.uniqueValues(Collections.singletonList(uniqueValue))
10491049
.build();
10501050
```
@@ -1053,13 +1053,13 @@ To read from more than one table in a single call, use multi-table mode — each
10531053

10541054
```java
10551055
GetRequestRecord fromTable1 = GetRequestRecord.builder()
1056-
.table("table1")
1057-
.ids(Arrays.asList("9fac9201-7b8a-4446-93f8-5244e1213bd1"))
1058-
.fields(Arrays.asList("card_number"))
1056+
.tableName("table1")
1057+
.skyflowIds(Arrays.asList("9fac9201-7b8a-4446-93f8-5244e1213bd1"))
1058+
.columns(Arrays.asList("card_number"))
10591059
.build();
10601060

10611061
GetRequestRecord fromTable2 = GetRequestRecord.builder()
1062-
.table("table2")
1062+
.tableName("table2")
10631063
.uniqueValues(Collections.singletonList(uniqueValue))
10641064
.build();
10651065

@@ -1204,7 +1204,7 @@ Delete records from a table by skyflow ID or unique value, in a single API call.
12041204
**Note:**
12051205

12061206
- This deletes the records themselves. [Bulk Delete Tokens](#bulk-delete-tokens) is a different operation — it removes tokens and leaves the underlying record in place.
1207-
- `table` is required, and exactly one of `ids` or `uniqueValues` must be supplied — both, or neither, fails validation.
1207+
- `tableName` is required, and exactly one of `skyflowIds` or `uniqueValues` must be supplied — both, or neither, fails validation.
12081208
- `uniqueValues` takes the same shape as in [Get](#get): one `Map<String, Object>` per record, holding the unique column-name/value pairs that identify it.
12091209

12101210
### Construct a delete request
@@ -1227,8 +1227,8 @@ public class DeleteExample {
12271227
));
12281228

12291229
DeleteRequest deleteRequest = DeleteRequest.builder()
1230-
.table("table1")
1231-
.ids(ids)
1230+
.tableName("table1")
1231+
.skyflowIds(ids)
12321232
.build();
12331233

12341234
DeleteResponse deleteResponse = vault.delete(deleteRequest);
@@ -1367,7 +1367,7 @@ This is the mental model to hold for every operation, bulk or unary:
13671367

13681368
| Layer | What it covers | How you see it |
13691369
|---|---|---|
1370-
| **Request-level** | The call could not be made or the whole call failed: invalid request shape, missing credentials, auth failure, payload over the 10,000-item limit. | A thrown `SkyflowException`. No results at all. |
1370+
| **Request-level** | The call could not be made or the whole call failed: invalid request shape, missing credentials, auth failure, payload over the 100,000-item limit. | A thrown `SkyflowException`. No results at all. |
13711371
| **Record-level** | The call succeeded, but individual records or tokens inside it did not. | A returned response. **Nothing is thrown.** Each entry in `getRecords()` reports its own `httpCode` and `error`. |
13721372

13731373
The second layer is what distinguishes `flowvault` from an all-or-nothing API: **a call that returns normally can still contain failures, and a call where every single record failed also returns normally rather than throwing.** Checking only for a thrown exception will silently miss failed records — always read the summary and the per-record results.
@@ -1474,7 +1474,7 @@ vault.bulkInsertAsync(insertRequest)
14741474
| Request ID | `getRequestId()` | The `x-request-id` header — useful for support escalations. |
14751475
| Details | `getDetails()` | `JsonArray` of additional error context from the server. Empty array for validation errors, `null` if the server response omitted the field. |
14761476

1477-
**Validation errors** (table name at the wrong level, empty token list, payload over 10,000 items, and similar) are thrown before any network call:
1477+
**Validation errors** (table name at the wrong level, empty token list, payload over 100,000 items, and similar) are thrown before any network call:
14781478

14791479
- `httpCode` is always `400`
14801480
- `requestId` and `grpcCode` are `null`
922 Bytes
Binary file not shown.

flowvault/samples/src/main/java/com/example/vault/DeleteExample.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public static void main(String[] args) {
3333
VaultConfig vaultConfig = new VaultConfig();
3434
vaultConfig.setVaultId("<YOUR_VAULT_ID>");
3535
vaultConfig.setClusterId("<YOUR_CLUSTER_ID>");
36-
vaultConfig.setEnv(Env.PROD);
36+
vaultConfig.setEnv(Env.DEV);
3737
vaultConfig.setCredentials(credentials);
3838

3939
// Step 3: Create Skyflow client instance with error logging
@@ -44,15 +44,13 @@ public static void main(String[] args) {
4444

4545
// Step 4: Prepare the skyflow IDs to delete.
4646
// Either ids or uniqueValues is required; specifying both fails validation.
47-
// Running this actually removes the record — rerunning GetExample/UpdateExample
48-
// against the same skyflowId afterward will then fail, since it's gone.
4947
List<String> ids = new ArrayList<>();
5048
ids.add("<YOUR_SKYFLOW_ID>");
5149

5250
// Step 5: Build and execute the delete request
5351
DeleteRequest request = DeleteRequest.builder()
54-
.table("<YOUR_TABLE_NAME>")
55-
.ids(ids)
52+
.tableName("<YOUR_TABLE_NAME>")
53+
.skyflowIds(ids)
5654
.build();
5755

5856
DeleteOptions options = DeleteOptions.builder()

flowvault/samples/src/main/java/com/example/vault/DetokenizeExample.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public static void main(String[] args) {
3232
VaultConfig vaultConfig = new VaultConfig();
3333
vaultConfig.setVaultId("<YOUR_VAULT_ID>");
3434
vaultConfig.setClusterId("<YOUR_CLUSTER_ID>");
35-
vaultConfig.setEnv(Env.PROD);
35+
vaultConfig.setEnv(Env.DEV);
3636
vaultConfig.setCredentials(credentials);
3737

3838
// Step 3: Create Skyflow client instance with error logging
@@ -43,11 +43,11 @@ public static void main(String[] args) {
4343

4444
// Step 4: Prepare the tokens to detokenize and any per-group redactions
4545
List<String> tokens = new ArrayList<>();
46-
tokens.add("<YOUR_TOKEN>");
46+
tokens.add("98579059870301");
4747

4848
List<TokenGroupRedactions> tokenGroupRedactions = new ArrayList<>();
4949
tokenGroupRedactions.add(TokenGroupRedactions.builder()
50-
.tokenGroupName("<YOUR_TOKEN_GROUP_NAME>")
50+
.tokenGroupName("nondeterministic")
5151
.redaction("plain_text")
5252
.build());
5353

flowvault/samples/src/main/java/com/example/vault/GetExample.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public static void main(String[] args) {
3838
vaultConfig.setVaultId("<YOUR_VAULT_ID>");
3939
vaultConfig.setVaultUrl("<YOUR_VAULT_URL>");
4040
// vaultConfig.setClusterId("<YOUR_CLUSTER_ID>");
41-
vaultConfig.setEnv(Env.PROD);
41+
vaultConfig.setEnv(Env.DEV);
4242
vaultConfig.setCredentials(credentials);
4343

4444
// Step 3: Create Skyflow client instance with error logging
@@ -53,14 +53,14 @@ public static void main(String[] args) {
5353
ids.add("<YOUR_SKYFLOW_ID_2>");
5454
List<ColumnRedactions> columnRedactions = new ArrayList<>();
5555
columnRedactions.add(ColumnRedactions.builder()
56-
.columnName("<YOUR_COLUMN_NAME_1>")
57-
.redaction("plain_text")
56+
.columnName("<YOUR_COLUMN_NAME>")
57+
.redaction("<YOUR_REDACTION_TYPE>")
5858
.build());
5959

6060
// Step 5: Build and execute the get request
6161
GetRequest request = GetRequest.builder()
62-
.table("<YOUR_TABLE_NAME>")
63-
.ids(ids)
62+
.tableName("<YOUR_TABLE_NAME>")
63+
.skyflowIds(ids)
6464
.columnRedactions(columnRedactions)
6565
.build();
6666

flowvault/samples/src/main/java/com/example/vault/InsertExample.java

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,25 @@ public static void main(String[] args) {
2525
try {
2626
// Step 1: Initialize credentials with the path to your service account key file
2727
// String filePath = "<YOUR_CREDENTIALS_FILE_PATH>";
28+
// Credentials credentials = new Credentials();
29+
// credentials.setToken("<YOUR_BEARER_TOKEN>");
30+
//
31+
// // Step 2: Configure the vault with required parameters
32+
// VaultConfig vaultConfig = new VaultConfig();
33+
// vaultConfig.setVaultId("<YOUR_VAULT_ID>");
34+
// vaultConfig.setClusterId("<YOUR_CLUSTER_ID>");
35+
// vaultConfig.setEnv(Env.DEV);
36+
// vaultConfig.setCredentials(credentials);
2837
Credentials credentials = new Credentials();
2938
credentials.setToken("<YOUR_BEARER_TOKEN>");
3039

3140
// Step 2: Configure the vault with required parameters
3241
VaultConfig vaultConfig = new VaultConfig();
3342
vaultConfig.setVaultId("<YOUR_VAULT_ID>");
43+
// vaultConfig.setVaultId("<YOUR_VAULT_ID>");
44+
// vaultConfig.setVaultUrl("<YOUR_VAULT_URL>");
3445
vaultConfig.setClusterId("<YOUR_CLUSTER_ID>");
35-
vaultConfig.setEnv(Env.PROD);
46+
vaultConfig.setEnv(Env.DEV);
3647
vaultConfig.setCredentials(credentials);
3748

3849
// Step 3: Create Skyflow client instance with error logging
@@ -43,19 +54,40 @@ public static void main(String[] args) {
4354

4455
// Step 4: Prepare the record to insert
4556
Map<String, Object> data = new HashMap<>();
46-
data.put("<YOUR_COLUMN_NAME_1>", "<YOUR_VALUE_1>");
57+
data.put("card_number", "41111111111111");
58+
// data.put("name", "name");
59+
// data.put("passport", "name");
60+
// data.put("email", "name@gm.com");
4761

62+
63+
64+
// data.put("name", "name");
65+
Map<String, Object> data2 = new HashMap<>();
66+
data2.put("card_number", "412323232323"); // cspell:disable-line -- deliberately misspelled to demonstrate an invalid-column error
67+
data2.put("name", "name");
68+
69+
List<String> columns = new ArrayList<>();
70+
columns.add("name");
71+
UpsertOptions upsertOptions = UpsertOptions.builder().uniqueColumns(columns).updateType("REPLACE").build();
4872
InsertRequestRecord record = InsertRequestRecord.builder()
73+
.data(data2)
74+
.tableName("uniqTable")
75+
.upsert(upsertOptions)
76+
.build();
77+
InsertRequestRecord record2 = InsertRequestRecord.builder()
4978
.data(data)
50-
.tableName("<YOUR_TABLE_NAME>")
79+
.tableName("table5")
80+
// .upsert(upsertOptions)
5181
.build();
5282

5383
List<InsertRequestRecord> records = new ArrayList<>();
5484
records.add(record);
85+
records.add(record2);
5586

5687
// Step 5: Build and execute the insert request
5788
InsertRequest request = InsertRequest.builder()
58-
// .tableName("<YOUR_TABLE_NAME>")
89+
// .tableName("uniqTable")
90+
// .upsert(upsertOptions)
5991
.records(records)
6092
.build();
6193
InsertOptions options = InsertOptions.builder()
@@ -64,7 +96,7 @@ public static void main(String[] args) {
6496
})
6597
.build();
6698
InsertResponse response = skyflowClient.vault().insert(request, options);
67-
99+
System.out.println("response"+ response.getRecords().size());
68100
// Step 6: Print every field on each response record.
69101
for (InsertResponseRecord insertedRecord : response.getRecords()) {
70102
System.out.println("tableName:\t" + insertedRecord.getTableName());

flowvault/samples/src/main/java/com/example/vault/QueryExample.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public static void main(String[] args) {
2727
VaultConfig vaultConfig = new VaultConfig();
2828
vaultConfig.setVaultId("<YOUR_VAULT_ID>");
2929
vaultConfig.setClusterId("<YOUR_CLUSTER_ID>");
30-
vaultConfig.setEnv(Env.PROD);
30+
vaultConfig.setEnv(Env.DEV);
3131
vaultConfig.setCredentials(credentials);
3232

3333
// Step 3: Create Skyflow client instance with error logging
@@ -38,7 +38,7 @@ public static void main(String[] args) {
3838

3939
// Step 4: Build and execute the query request
4040
QueryRequest request = QueryRequest.builder()
41-
.query("SELECT * FROM <YOUR_TABLE_NAME> LIMIT 1")
41+
.query("SELECT * FROM table1")
4242
.build();
4343

4444
QueryResponse response = skyflowClient.vault().query(request);

0 commit comments

Comments
 (0)