From 2df6db36c85c27d424d54e9c168ef4ea09c5c08c Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Wed, 26 Apr 2023 13:14:01 -0400 Subject: [PATCH] feat(ext/kv): add more atomic operation helpers (#18854) Co-authored-by: losfair Co-authored-by: Luca Casonato --- cli/tests/unit/kv_test.ts | 30 ++++++++++++++++++++++++++++++ cli/tsc/dts/lib.deno.unstable.d.ts | 19 +++++++++++++++++-- ext/kv/01_db.ts | 23 +++++++++++++++-------- 3 files changed, 62 insertions(+), 10 deletions(-) diff --git a/cli/tests/unit/kv_test.ts b/cli/tests/unit/kv_test.ts index 60cf11b8ef..0af8f338d2 100644 --- a/cli/tests/unit/kv_test.ts +++ b/cli/tests/unit/kv_test.ts @@ -219,6 +219,36 @@ dbTest("compare and mutate not exists", async (db) => { assertEquals(res, null); }); +dbTest("atomic mutation helper (sum)", async (db) => { + await db.set(["t"], new Deno.KvU64(42n)); + assertEquals((await db.get(["t"])).value, new Deno.KvU64(42n)); + + await db.atomic().sum(["t"], 1n).commit(); + assertEquals((await db.get(["t"])).value, new Deno.KvU64(43n)); +}); + +dbTest("atomic mutation helper (min)", async (db) => { + await db.set(["t"], new Deno.KvU64(42n)); + assertEquals((await db.get(["t"])).value, new Deno.KvU64(42n)); + + await db.atomic().min(["t"], 1n).commit(); + assertEquals((await db.get(["t"])).value, new Deno.KvU64(1n)); + + await db.atomic().min(["t"], 2n).commit(); + assertEquals((await db.get(["t"])).value, new Deno.KvU64(1n)); +}); + +dbTest("atomic mutation helper (max)", async (db) => { + await db.set(["t"], new Deno.KvU64(42n)); + assertEquals((await db.get(["t"])).value, new Deno.KvU64(42n)); + + await db.atomic().max(["t"], 41n).commit(); + assertEquals((await db.get(["t"])).value, new Deno.KvU64(42n)); + + await db.atomic().max(["t"], 43n).commit(); + assertEquals((await db.get(["t"])).value, new Deno.KvU64(43n)); +}); + dbTest("compare multiple and mutate", async (db) => { await db.set(["t1"], "1"); await db.set(["t2"], "2"); diff --git a/cli/tsc/dts/lib.deno.unstable.d.ts b/cli/tsc/dts/lib.deno.unstable.d.ts index cf6cedf414..dc3bfcfc01 100644 --- a/cli/tsc/dts/lib.deno.unstable.d.ts +++ b/cli/tsc/dts/lib.deno.unstable.d.ts @@ -1646,7 +1646,8 @@ declare namespace Deno { * - `sum` - Adds the given value to the existing value of the key. Both the * value specified in the mutation, and any existing value must be of type * `Deno.KvU64`. If the key does not exist, the value is set to the given - * value (summed with 0). + * value (summed with 0). If the result of the sum overflows an unsigned + * 64-bit integer, the result is wrapped around. * - `max` - Sets the value of the key to the maximum of the existing value * and the given value. Both the value specified in the mutation, and any * existing value must be of type `Deno.KvU64`. If the key does not exist, @@ -1845,9 +1846,23 @@ declare namespace Deno { */ mutate(...mutations: KvMutation[]): this; /** - * Shortcut for creating a sum mutation. + * Shortcut for creating a `sum` mutation. This method wraps `n` in a + * {@linkcode Deno.KvU64}, so the value of `n` must be in the range + * `[0, 2^64-1]`. */ sum(key: KvKey, n: bigint): this; + /** + * Shortcut for creating a `min` mutation. This method wraps `n` in a + * {@linkcode Deno.KvU64}, so the value of `n` must be in the range + * `[0, 2^64-1]`. + */ + min(key: KvKey, n: bigint): this; + /** + * Shortcut for creating a `max` mutation. This method wraps `n` in a + * {@linkcode Deno.KvU64}, so the value of `n` must be in the range + * `[0, 2^64-1]`. + */ + max(key: KvKey, n: bigint): this; /** * 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. diff --git a/ext/kv/01_db.ts b/ext/kv/01_db.ts index 1a7b27dac7..da29a09521 100644 --- a/ext/kv/01_db.ts +++ b/ext/kv/01_db.ts @@ -211,14 +211,6 @@ class AtomicOperation { return this; } - sum(key: Deno.KvKey, n: bigint): this { - return this.mutate({ - type: "sum", - key, - value: new KvU64(n), - }); - } - mutate(...mutations: Deno.KvMutation[]): this { for (const mutation of mutations) { const key = mutation.key; @@ -249,6 +241,21 @@ class AtomicOperation { return this; } + sum(key: Deno.KvKey, n: bigint): this { + this.#mutations.push([key, "sum", serializeValue(new KvU64(n))]); + return this; + } + + min(key: Deno.KvKey, n: bigint): this { + this.#mutations.push([key, "min", serializeValue(new KvU64(n))]); + return this; + } + + max(key: Deno.KvKey, n: bigint): this { + this.#mutations.push([key, "max", serializeValue(new KvU64(n))]); + return this; + } + set(key: Deno.KvKey, value: unknown): this { this.#mutations.push([key, "set", serializeValue(value)]); return this;