Skip to content

Commit 9604fd3

Browse files
authored
[BLY-66] direct upload pparams (#28)
* bucket check and async setup clients perform direct setup by default * (python) more consistent json for internal api all requests and response are JSON. all binary payloads are explicitly encoded as base64 within api.py, and decoded back to bytes before leaving api.py. User-facing code, e.g. bucket.py and bucket_service.py, should not see base64 wrangling. * Support async for all ops refactor api.py to be async-first use new asyncio loops to support non-async interface; cannot call non-async methods from async context * [js] update client to work with unified service bump both versions to 0.2.1 disable npm/pypi publish except on manual workflow run * disable request compression * fix workflow tests update standalone Spiral test server to use new JSON interface
1 parent 7740f75 commit 9604fd3

File tree

23 files changed

+1017
-822
lines changed

23 files changed

+1017
-822
lines changed

.github/workflows/build-js.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ jobs:
6767
client-publish:
6868
name: Publish JavaScript SDK
6969
runs-on: ubuntu-latest
70-
if: ${{ inputs.publish || github.ref == 'refs/heads/main' }}
70+
if: ${{ inputs.publish }}
7171
needs: [client-build]
7272
steps:
7373
- uses: actions/checkout@v3

.github/workflows/build-python.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ jobs:
144144
publish:
145145
name: Publish
146146
runs-on: ubuntu-latest
147-
if: ${{ inputs.publish || github.ref == 'refs/heads/main' }}
147+
if: ${{ inputs.publish }}
148148
needs: [linux, macos, windows, sdist]
149149
steps:
150150
- uses: actions/download-artifact@v3

e2e-tests/api.ts

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,29 @@ function generateKeys(n: number, seed: number = 0): string[] {
3030
);
3131
}
3232

33+
34+
async function generateKVPairs(n: number, seed: number, itemSize: number): Promise<{ [key: string]: Uint8Array }> {
35+
const keys = generateKeys(n, seed);
36+
const kvPairs: { [key: string]: Uint8Array } = {};
37+
38+
for (const key of keys) {
39+
kvPairs[key] = await keyToValue(key, itemSize);
40+
}
41+
42+
return kvPairs;
43+
}
44+
45+
46+
function getRandomKey(kvP: { [key: string]: Uint8Array }): string {
47+
return Object.keys(kvP)[Math.floor(Math.random() * Object.keys(kvP).length)];
48+
}
49+
50+
3351
function generateBucketName(): string {
3452
return 'api-tester-' + Math.random().toString(16).substring(2, 10);
3553
}
3654

37-
async function testBlyssService(endpoint: string = 'https://dev2.api.blyss.dev') {
38-
const apiKey = process.env.BLYSS_API_KEY;
39-
if (!apiKey) {
40-
throw new Error('BLYSS_API_KEY environment variable is not set');
41-
}
55+
async function testBlyssService(endpoint: string, apiKey: string) {
4256
console.log('Using key: ' + apiKey + ' to connect to ' + endpoint);
4357
const client: Client = await new blyss.Client(
4458
{
@@ -55,50 +69,44 @@ async function testBlyssService(endpoint: string = 'https://dev2.api.blyss.dev')
5569
// generate N random keys
5670
const N = 100;
5771
const itemSize = 32;
58-
let localKeys = generateKeys(N);
59-
function getRandomKey(): string {
60-
return localKeys[Math.floor(Math.random() * localKeys.length)];
61-
}
72+
let kvPairs = await generateKVPairs(N, 0, itemSize);
73+
6274
// write all N keys
6375
await bucket.write(
64-
await Promise.all(localKeys.map(
65-
async (k) => ({
66-
k: await keyToValue(k, itemSize)
67-
})
68-
))
76+
kvPairs
6977
);
7078
console.log(`Wrote ${N} keys`);
7179

7280
// read a random key
73-
let testKey = getRandomKey();
81+
let testKey = getRandomKey(kvPairs);
82+
console.log(`Reading key ${testKey}`)
83+
await bucket.setup();
84+
console.log("1111");
7485
let value = await bucket.privateRead(testKey);
7586
await verifyRead(testKey, value);
7687
console.log(`Read key ${testKey}`);
7788

7889
// delete testKey from the bucket, and localData.
7990
await bucket.deleteKey(testKey);
80-
localKeys.splice(localKeys.indexOf(testKey), 1);
91+
8192
console.log(`Deleted key ${testKey}`);
8293

8394
// write a new value
8495
testKey = 'newKey0';
85-
await bucket.write({ testKey: keyToValue(testKey, itemSize) });
86-
localKeys.push(testKey);
96+
let newValue = await keyToValue(testKey, itemSize);
97+
await bucket.write({ testKey: newValue });
98+
kvPairs[testKey] = newValue;
8799
console.log(`Wrote key ${testKey}`);
88100

89101
// clear all keys
90102
await bucket.clearEntireBucket();
91-
localKeys = [];
103+
kvPairs = {};
92104
console.log('Cleared bucket');
93105

94106
// write a new set of N keys
95-
localKeys = generateKeys(N, 1);
107+
kvPairs = await generateKVPairs(N, 1, itemSize);
96108
await bucket.write(
97-
await Promise.all(localKeys.map(
98-
async (k) => ({
99-
k: await keyToValue(k, itemSize)
100-
})
101-
))
109+
kvPairs
102110
);
103111
console.log(`Wrote ${N} keys`);
104112

@@ -109,7 +117,7 @@ async function testBlyssService(endpoint: string = 'https://dev2.api.blyss.dev')
109117
console.log(await bucket.info());
110118

111119
// random read
112-
testKey = getRandomKey();
120+
testKey = getRandomKey(kvPairs);
113121
value = await bucket.privateRead(testKey);
114122
await verifyRead(testKey, value);
115123
console.log(`Read key ${testKey}`);
@@ -119,11 +127,15 @@ async function testBlyssService(endpoint: string = 'https://dev2.api.blyss.dev')
119127
console.log(`Destroyed bucket ${bucket.name}`);
120128
}
121129

122-
async function main() {
123-
const endpoint = "https://dev2.api.blyss.dev"
124-
console.log('Testing Blyss service at URL ' + endpoint);
125-
await testBlyssService(endpoint);
130+
async function main(endpoint: string, apiKey: string) {
131+
if (!apiKey) {
132+
throw new Error('BLYSS_API_KEY environment variable is not set');
133+
}
134+
await testBlyssService(endpoint, apiKey);
126135
console.log('All tests completed successfully.');
127136
}
128137

129-
main();
138+
// get endpoint and api key from command line, or fallback to defaults
139+
const endpoint = process.argv[2] || 'https://beta.api.blyss.dev';
140+
const apiKey = process.argv[3] || process.env.BLYSS_API_KEY;
141+
main(endpoint, apiKey);

e2e-tests/tests/simple.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,20 @@ export default async function main(port: string) {
88

99
console.log(bucket.metadata);
1010

11+
// buckets are bytes-in/bytes-out. SDK write() will automatically serialize as UTF-8.
1112
await bucket.write({
1213
Ohio: 'Columbus',
1314
California: 'Sacramento'
1415
});
1516

16-
let capital = await bucket.privateRead('Ohio');
17+
// but reads are always bytes-out, and must be decoded.
18+
let capital = new TextDecoder().decode(await bucket.privateRead('Ohio'));
1719
if (capital !== 'Columbus') {
1820
throw 'Incorrect result.';
1921
}
2022

21-
capital = await bucket.privateRead('California');
23+
// capital = await bucket.privateRead('California');
24+
capital = new TextDecoder().decode(await bucket.privateRead('California'));
2225
if (capital !== 'Sacramento') {
2326
throw 'Incorrect result.';
2427
}

js/bridge/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/bucket/bucket.ts

Lines changed: 20 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -152,34 +152,27 @@ export class Bucket {
152152
keys: string[]
153153
): Promise<any[]> {
154154
if (!this.uuid || !this.check(this.uuid)) {
155+
console.log('Setting up client');
155156
await this.setup();
156157
}
157158

158-
const queries: { key: string; queryData: Uint8Array }[] = [];
159+
// For each key, generate a query, encode it as base64, and append it to a list.
160+
let queries: Uint8Array[] = [];
159161
for (const key of keys) {
160162
const rowIdx = this.lib.getRow(key);
161163
const queryData = this.lib.generateQuery(this.uuid, rowIdx);
162-
queries.push({ key, queryData });
164+
queries.push(queryData);
163165
}
164166

165-
const endResults = [];
166-
const batches = Math.ceil(queries.length / this.batchSize);
167-
for (let i = 0; i < batches; i++) {
168-
const queriesForBatch = queries.slice(
169-
i * this.batchSize,
170-
(i + 1) * this.batchSize
171-
);
172-
173-
const queryBatch = serializeChunks(queriesForBatch.map(x => x.queryData));
174-
const rawResultChunks = await this.getRawResponse(queryBatch);
175-
const rawResults = deserializeChunks(rawResultChunks);
167+
// Send the list of queries to the server.
168+
const rawResults = await this.api.privateReadJson(this.name, queries);
176169

177-
const batchEndResults = await Promise.all(
178-
rawResults.map((r, i) => this.getEndResult(queriesForBatch[i].key, r))
179-
);
180170

181-
endResults.push(...batchEndResults);
182-
}
171+
// For each query, decrypt the result, decompress it, and extract the
172+
// result.
173+
const endResults = await Promise.all(
174+
rawResults.map((r, i) => this.getEndResult(keys[i], r))
175+
);
183176

184177
return endResults;
185178
}
@@ -328,12 +321,6 @@ export class Bucket {
328321
this.name = newBucketName;
329322
}
330323

331-
/** Gets info on all keys in this bucket. */
332-
async listKeys(): Promise<KeyInfo[]> {
333-
this.ensureSpiral();
334-
return await this.api.listKeys(this.name);
335-
}
336-
337324
/**
338325
* Make a write to this bucket.
339326
*
@@ -343,27 +330,20 @@ export class Bucket {
343330
* 1024 UTF-8 bytes.
344331
*/
345332
async write(
346-
keyValuePairs: { [key: string]: any }
333+
keyValuePairs: { [key: string]: Uint8Array | string | null }
347334
) {
348335
this.ensureSpiral();
349-
350-
const data = [];
336+
// convert any string KV pairs to Uint8Array
337+
const kvPairs: { [key: string]: Uint8Array | null } = {};
351338
for (const key in keyValuePairs) {
352-
if (Object.prototype.hasOwnProperty.call(keyValuePairs, key)) {
353-
const value = keyValuePairs[key];
354-
const valueBytes = serialize(value);
355-
const keyBytes = new TextEncoder().encode(key);
356-
const serializedKeyValue = wrapKeyValue(keyBytes, valueBytes);
357-
data.push(serializedKeyValue);
358-
// const kv = {
359-
// key: key,
360-
// value: Buffer.from(valueBytes).toString('base64')
361-
// }
339+
const value = keyValuePairs[key];
340+
if (!(value instanceof Uint8Array)) {
341+
kvPairs[key] = new TextEncoder().encode(value);
342+
} else {
343+
kvPairs[key] = value;
362344
}
363345
}
364-
const concatenatedData = concatBytes(data);
365-
// const concatenatedData = serialize(data);
366-
await this.api.write(this.name, concatenatedData);
346+
await this.api.write(this.name, kvPairs);
367347
}
368348

369349
/**

js/bucket/bucket_service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ export class BucketService {
9797
const parameters = { ...DEFAULT_BUCKET_PARAMETERS, ...params };
9898
const bucketCreateReq = {
9999
name: bucketName,
100-
parameters: JSON.stringify(parameters),
100+
parameters,
101101
open_access: openAccess
102102
};
103103
await this.api.create(JSON.stringify(bucketCreateReq));

0 commit comments

Comments
 (0)