Skip to content

Commit

Permalink
feat: add support for expiresIn
Browse files Browse the repository at this point in the history
Closes #3

Co-authored-by: Yudai Nakata <13291527+yudai-nkt@users.noreply.github.com>
  • Loading branch information
kitsonk and yudai-nkt committed Sep 7, 2023
1 parent caec28b commit 6350e77
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 6 deletions.
1 change: 1 addition & 0 deletions _test_util.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { assert } from "https://deno.land/std@0.186.0/testing/asserts.ts";
export { delay } from "https://deno.land/std@0.186.0/async/delay.ts";
export {
assert,
assertEquals,
Expand Down
20 changes: 20 additions & 0 deletions batchedAtomic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
assert,
assertEquals,
assertNotEquals,
delay,
setup,
teardown,
} from "./_test_util.ts";
Expand Down Expand Up @@ -41,3 +42,22 @@ Deno.test({
return teardown();
},
});

Deno.test({
name: "batched atomic supports expiresIn option",
ignore: true, // not currently working in Deno CLI
async fn() {
const kv = await setup();
const operation = batchedAtomic(kv);
operation.set(["hello"], "deno kv", { expireIn: 100 });
const actual = await operation.commit();
assertEquals(actual.length, 1);
assert(actual[0].ok);
const res1 = await kv.get<string>(["hello"]);
assertEquals(res1.value, "deno kv");
await delay(700);
const res2 = await kv.get<string>(["hello"]);
assertEquals(res2.value, null);
return teardown();
},
});
11 changes: 9 additions & 2 deletions batchedAtomic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,16 @@ export class BatchedAtomicOperation {
/**
* Add to the operation a mutation that sets the value of the specified key
* to the specified value if all checks pass during the commit.
*
* Optionally an `expireIn` option can be specified to set a time-to-live
* (TTL) for the key. The TTL is specified in milliseconds, and the key will
* be deleted from the database at earliest after the specified number of
* milliseconds have elapsed. Once the specified duration has passed, the
* key may still be visible for some additional time. If the `expireIn`
* option is not specified, the key will not expire.
*/
set(key: Deno.KvKey, value: unknown): this {
return this.#enqueue("set", [key, value]);
set(key: Deno.KvKey, value: unknown, options?: { expireIn?: number }): this {
return this.#enqueue("set", [key, value, options]);
}

/**
Expand Down
24 changes: 20 additions & 4 deletions blob.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,15 @@ function writeArrayBuffer(
key: Deno.KvKey,
blob: ArrayBufferLike,
start = 0,
options?: { expireIn?: number },
): [count: number, operation: BatchedAtomicOperation] {
const buffer = new Uint8Array(blob);
let offset = 0;
let count = start;
while (buffer.byteLength > offset) {
count++;
const chunk = buffer.subarray(offset, offset + CHUNK_SIZE);
operation.set([...key, BLOB_KEY, count], chunk);
operation.set([...key, BLOB_KEY, count], chunk, options);
offset += CHUNK_SIZE;
}
return [count, operation];
Expand All @@ -99,10 +100,17 @@ async function writeStream(
operation: BatchedAtomicOperation,
key: Deno.KvKey,
stream: ReadableStream<Uint8Array>,
options?: { expireIn?: number },
): Promise<[count: number, operation: BatchedAtomicOperation]> {
let start = 0;
for await (const chunk of stream) {
[start, operation] = writeArrayBuffer(operation, key, chunk, start);
[start, operation] = writeArrayBuffer(
operation,
key,
chunk,
start,
options,
);
}
return [start, operation];
}
Expand Down Expand Up @@ -204,6 +212,13 @@ export function get(
* The function chunks up the blob into parts which deno be stored in Deno KV
* and should be retrieved back out using the {@linkcode get} function.
*
* Optionally an `expireIn` option can be specified to set a time-to-live
* (TTL) for the key. The TTL is specified in milliseconds, and the key will
* be deleted from the database at earliest after the specified number of
* milliseconds have elapsed. Once the specified duration has passed, the
* key may still be visible for some additional time. If the `expireIn`
* option is not specified, the key will not expire.
*
* ### Example
*
* ```ts
Expand All @@ -220,14 +235,15 @@ export async function set(
kv: Deno.Kv,
key: Deno.KvKey,
blob: ArrayBufferLike | ReadableStream<Uint8Array>,
options?: { expireIn?: number },
): Promise<void> {
const items = await keys(kv, { prefix: [...key, BLOB_KEY] });
let operation = batchedAtomic(kv);
let count;
if (blob instanceof ReadableStream) {
[count, operation] = await writeStream(operation, key, blob);
[count, operation] = await writeStream(operation, key, blob, options);
} else {
[count, operation] = writeArrayBuffer(operation, key, blob);
[count, operation] = writeArrayBuffer(operation, key, blob, 0, options);
}
operation = deleteKeys(operation, key, count, items.length);
await operation.commit();
Expand Down
1 change: 1 addition & 0 deletions deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 6350e77

Please sign in to comment.