Skip to content

Commit

Permalink
feat: KV store generation integer follow up (#1029) (#1108)
Browse files Browse the repository at this point in the history
  • Loading branch information
vcarvajal-sigsci authored Feb 10, 2025
1 parent 532afb5 commit 8a076da
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 3 deletions.
5 changes: 5 additions & 0 deletions documentation/docs/kv-store/KVStore/prototype/put.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ put(key, value, options?)
- TTL for the entry
- `mode` _: 'overwrite' | 'add' | 'append' | 'prepend'_ _**optional**_
- Insert mode, defaults to 'overwrite'
- `gen` _: number_ _**optional**_
- 'generation' header specific to the version of an entry key
### Return value
Expand All @@ -51,6 +53,9 @@ If the `this` value does not inherit from `KVStore.prototype`, a [`TypeError`](.
- Starts with the string `".well-known/acme-challenge/"`
- Contains any of the characters `"#;?^|\n\r"`
- Is longer than 1024 characters
- `TypeError`
- If the provided `gen`:
- Is not an number
## Examples
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1389,7 +1389,31 @@ const debug = sdkVersion.endsWith('-debug');
`(await entry.arrayBuffer()) instanceof ArrayBuffer`,
);
});

routes.set('/kv-store-options/gen', async () => {
let store = new KVStore(KV_STORE_NAME);
let key = `entry-options`;
await store.put(key, 'body op', { gen: 2 });
let entry = await store.get(key);
let result = entry.body;
strictEqual(
result instanceof ReadableStream,
true,
`entry.options instanceof ReadableStream`,
);
let text = await streamToString(result);
strictEqual(text, 'body op', `entry.body contents as string`);
});
routes.set('/kv-store-options/gen-invalid', async () => {
await assertRejects(
async () => {
const store = new KVStore(KV_STORE_NAME);
let key = `entry-options-gen-invalid`;
await store.put(key, 'body Nan', { gen: '2' });
},
TypeError,
`KVStore.insert: gen must be an integer`,
);
});
routes.set('/kv-store-entry/body', async () => {
let store = new KVStore(KV_STORE_NAME);
let key = `entry-body`;
Expand Down
2 changes: 2 additions & 0 deletions integration-tests/js-compute/fixtures/module-mode/tests.json
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,8 @@
"GET /kv-store-entry/json/valid": { "flake": true },
"GET /kv-store-entry/json/invalid": { "flake": true },
"GET /kv-store-entry/arrayBuffer/valid": { "flake": true },
"GET /kv-store-options/gen": { "flake": true },
"GET /kv-store-options/gen-invalid": { "flake": true },
"GET /kv-store-entry/body": { "flake": true },
"GET /kv-store-entry/bodyUsed": { "flake": true },
"GET /transform-stream/identity": {
Expand Down
7 changes: 6 additions & 1 deletion integration-tests/js-compute/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,14 @@ async function setupKVStore() {
async function setupSecretStore() {
let stores = await (async function () {
try {
return JSON.parse(
res = JSON.parse(
await zx`fastly secret-store list --quiet --json --token $FASTLY_API_TOKEN`,
);
if (res == null) {
return [];
} else {
return res;
}
} catch {
return [];
}
Expand Down
20 changes: 19 additions & 1 deletion runtime/fastly/builtins/kv-store.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,7 @@ bool KVStore::put(JSContext *cx, unsigned argc, JS::Value *vp) {
// used only if we have to do a custom text encoding
host_api::HostString metadata_str;
std::optional<uint32_t> ttl = std::nullopt;
std::optional<uint64_t> if_gen = std::nullopt;
std::optional<std::tuple<const uint8_t *, size_t>> metadata = std::nullopt;
std::optional<host_api::KVStore::InsertMode> mode = std::nullopt;
if (args.get(2).isObject()) {
Expand All @@ -474,6 +475,23 @@ bool KVStore::put(JSContext *cx, unsigned argc, JS::Value *vp) {
ttl = parsed;
}

JS::RootedValue gen_val(cx);
if (!JS_GetProperty(cx, opts_val, "gen", &gen_val)) {
return false;
}

if (!gen_val.isNullOrUndefined()) {
if (gen_val.isNumber()) {
if (gen_val.toNumber()) {
if_gen.emplace(gen_val.toNumber());
}
}
if (!if_gen.has_value()) {
api::throw_error(cx, api::Errors::TypeError, "KVStore.insert", "gen", "be an integer");
return ReturnPromiseRejectedWithPendingError(cx, args);
}
}

if (!JS_GetProperty(cx, opts_val, "metadata", &metadata_val)) {
return false;
}
Expand Down Expand Up @@ -626,7 +644,7 @@ bool KVStore::put(JSContext *cx, unsigned argc, JS::Value *vp) {
}
}

auto insert_res = kv_store(self).insert(key_chars, body, mode, std::nullopt, metadata, ttl);
auto insert_res = kv_store(self).insert(key_chars, body, mode, if_gen, metadata, ttl);
if (auto *err = insert_res.to_err()) {
// Ensure that we throw an exception for all unexpected host errors.
HANDLE_ERROR(cx, *err);
Expand Down
4 changes: 4 additions & 0 deletions types/kv-store.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ declare module 'fastly:kv-store' {
* Insert mode, defaults to 'overwrite'.
*/
mode?: 'overwrite' | 'add' | 'append' | 'prepend';
/**
* If generation match integer.
*/
gen?: number;
},
): Promise<undefined>;

Expand Down

0 comments on commit 8a076da

Please sign in to comment.