Skip to content

Commit

Permalink
chore: refactor max transaction size
Browse files Browse the repository at this point in the history
  • Loading branch information
cknight committed Jul 6, 2023
1 parent 2bebfc7 commit 2082c0c
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 38 deletions.
37 changes: 26 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@
Collection of utilities for working with Deno KV.

## multiSet
Set multiple key/value pairs into KV. Sets are grouped together into transactions for higher performance than setting individually.

Set multiple key/value pairs into KV. Sets are grouped together into
transactions for higher performance than setting individually.

```ts
import { MultiResult, multiSet } from "https://raw.githubusercontent.com/cknight/kv-utils/1.0.0/mod.ts";
import {
MultiResult,
multiSet,
} from "https://raw.githubusercontent.com/cknight/kv-utils/1.0.0/mod.ts";

const keyValues = new Map<Deno.KvKey, unknown>();
for (let i = 0; i < 100; i++) {
Expand All @@ -21,13 +26,16 @@ if (!result.ok) {
```

## multiDelete
Delete multiple key/value pairs from KV. Deletes are grouped together into transactions for higher performance than deleting individually.

Delete multiple key/value pairs from KV. Deletes are grouped together into
transactions for higher performance than deleting individually.

Delete from an array of keys:

```ts
import { multiDelete } from "https://raw.githubusercontent.com/cknight/kv-utils/1.0.0/mod.ts";

const keys:Deno.KvKey[] = [];
const keys: Deno.KvKey[] = [];
for (let i = 0; i < 100; i++) {
keys.push(["key", i]);
}
Expand All @@ -39,11 +47,13 @@ if (!result.ok) {
}
```

Or delete from a [list selector](https://deno.land/api?unstable=&s=Deno.KvListSelector)
Or delete from a
[list selector](https://deno.land/api?unstable=&s=Deno.KvListSelector)

```ts
import { multiDelete } from "https://raw.githubusercontent.com/cknight/kv-utils/1.0.0/mod.ts";

const result = await multiDelete({prefix: ["key"], end: ["key", 1]});
const result = await multiDelete({ prefix: ["key"], end: ["key", 1] });

if (!result.ok) {
const failedToDeleteKeys = result.failedKeys;
Expand All @@ -53,9 +63,9 @@ if (!result.ok) {

## wipeKvStore

A shorthand, explicit, way to clear your KV store of all data.
A shorthand, explicit, way to clear your KV store of all data.

__Warning__: This will remove all data from your KV store!
**Warning**: This will remove all data from your KV store!

```ts
import { wipeKvStore } from "https://raw.githubusercontent.com/cknight/kv-utils/1.0.0/mod.ts";
Expand All @@ -69,12 +79,18 @@ if (!result.ok) {
```

## count
For a given [list selector](https://deno.land/api?unstable=&s=Deno.KvListSelector), count the number of matching keys. Note, this works by fetching all the data and then counting it, which is inefficient but all we have to work with at this stage. Keep an eye on [this issue](https://github.com/denoland/deno/issues/18965) which proposes a native count function in KV.

For a given
[list selector](https://deno.land/api?unstable=&s=Deno.KvListSelector), count
the number of matching keys. Note, this works by fetching all the data and then
counting it, which is inefficient but all we have to work with at this stage.
Keep an eye on [this issue](https://github.com/denoland/deno/issues/18965) which
proposes a native count function in KV.

```ts
import { count } from "https://raw.githubusercontent.com/cknight/kv-utils/1.0.0/mod.ts";

const keyCount = await count({prefix: ["key"]});
const keyCount = await count({ prefix: ["key"] });
```

## countAll
Expand All @@ -86,4 +102,3 @@ import { countAll } from "https://raw.githubusercontent.com/cknight/kv-utils/1.0

const numOfKeys = await countAll();
```

10 changes: 7 additions & 3 deletions mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export interface MultiResult {
failedKeys?: Deno.KvKey[];
}

const MAX_TRANSACTION_SIZE = 10;

/**
* Set multiple key value pairs into the KV store
* @param keyValues Map of key value pairs to insert
Expand All @@ -21,7 +23,7 @@ export async function multiSet(
for (const [key, value] of keyValues) {
atomic.set(key, value);
keysInAction.push(key);
if (++count == 10) {
if (++count == MAX_TRANSACTION_SIZE) {
try {
await atomic.commit();
} catch (e) {
Expand Down Expand Up @@ -51,7 +53,9 @@ export async function multiSet(
* @returns object with ok property indicating success or failure and optional failedKeys
* property containing keys that failed to delete
*/
export async function multiDelete(source: Deno.KvKey[] | Deno.KvListSelector): Promise<MultiResult> {
export async function multiDelete(
source: Deno.KvKey[] | Deno.KvListSelector,
): Promise<MultiResult> {
let atomic = kv.atomic();
let count = 0;
let keysInAction = [];
Expand All @@ -69,7 +73,7 @@ export async function multiDelete(source: Deno.KvKey[] | Deno.KvListSelector): P
for (const key of keys) {
atomic.delete(key);
keysInAction.push(key);
if (++count == 10) {
if (++count == MAX_TRANSACTION_SIZE) {
try {
await atomic.commit();
} catch (e) {
Expand Down
55 changes: 31 additions & 24 deletions mod_test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { assertEquals } from "https://deno.land/std@0.193.0/testing/asserts.ts";
import { test } from "./test_deps.ts";
import { multiDelete, multiSet, count, countAll, wipeKvStore, MultiResult } from "./mod.ts";
import {
count,
countAll,
multiDelete,
MultiResult,
multiSet,
wipeKvStore,
} from "./mod.ts";

test({
name: "No keys added - empty map",
Expand All @@ -23,7 +30,7 @@ test({
await multiSet(new Map([[["asdf"], "asdf"]]));
assertEquals(await countAll(), 1);
});
}
},
});

test({
Expand All @@ -39,15 +46,15 @@ test({
await multiSet(keyValues);
assertEquals(await countAll(), 10);
});
}
},
});

test({
name: "115 keys added",
async fn(t) {
await resetDatabase(t);
await insert115Keys(t);
}
},
});

test({
Expand All @@ -59,7 +66,7 @@ test({
await multiDelete([]);
assertEquals(await countAll(), 115);
});
}
},
});

test({
Expand All @@ -71,7 +78,7 @@ test({
await multiDelete([["key", 1]]);
assertEquals(await countAll(), 114);
});
}
},
});

test({
Expand All @@ -87,7 +94,7 @@ test({
await multiDelete(keys);
assertEquals(await countAll(), 105);
});
}
},
});

test({
Expand All @@ -107,7 +114,7 @@ test({
await multiDelete(keys);
assertEquals(await countAll(), 1);
});
}
},
});

test({
Expand All @@ -116,10 +123,10 @@ test({
await resetDatabase(t);
await insert115Keys(t);
await t.step("0 keys deleted from list", async () => {
await multiDelete({prefix: ["doesNotExist"]});
await multiDelete({ prefix: ["doesNotExist"] });
assertEquals(await countAll(), 115);
});
}
},
});

test({
Expand All @@ -128,10 +135,10 @@ test({
await resetDatabase(t);
await insert115Keys(t);
await t.step("1 key deleted from list", async () => {
await multiDelete({prefix: ["key"], end: ["key", 1]});
await multiDelete({ prefix: ["key"], end: ["key", 1] });
assertEquals(await countAll(), 114);
});
}
},
});

test({
Expand All @@ -140,10 +147,10 @@ test({
await resetDatabase(t);
await insert115Keys(t);
await t.step("10 keys deleted from list", async () => {
await multiDelete({prefix: ["key"], end: ["key", 10]});
await multiDelete({ prefix: ["key"], end: ["key", 10] });
assertEquals(await countAll(), 105);
});
}
},
});

test({
Expand All @@ -152,10 +159,10 @@ test({
await resetDatabase(t);
await insert115Keys(t);
await t.step("115 keys deleted from list", async () => {
await multiDelete({prefix: ["key"]});
await multiDelete({ prefix: ["key"] });
assertEquals(await countAll(), 0);
});
}
},
});

test({
Expand All @@ -164,9 +171,9 @@ test({
await resetDatabase(t);
await insert115Keys(t);
await t.step("count 0 keys", async () => {
assertEquals(await count({prefix: ["doesNotExist"]}), 0);
assertEquals(await count({ prefix: ["doesNotExist"] }), 0);
});
}
},
});

test({
Expand All @@ -175,9 +182,9 @@ test({
await resetDatabase(t);
await insert115Keys(t);
await t.step("count 1 key", async () => {
assertEquals(await count({prefix: ["key"], end: ["key", 1]}), 1);
assertEquals(await count({ prefix: ["key"], end: ["key", 1] }), 1);
});
}
},
});

test({
Expand All @@ -186,12 +193,12 @@ test({
await resetDatabase(t);
await insert115Keys(t);
await t.step("count 10 keys", async () => {
assertEquals(await count({prefix: ["key"], end: ["key", 10]}), 10);
assertEquals(await count({ prefix: ["key"], end: ["key", 10] }), 10);
});
}
},
});

async function resetDatabase(t:Deno.TestContext) {
async function resetDatabase(t: Deno.TestContext) {
await t.step("Reset database", async () => {
await wipeKvStore();
assertEquals(await countAll(), 0);
Expand All @@ -207,4 +214,4 @@ async function insert115Keys(t: Deno.TestContext) {
await multiSet(keyValues);
assertEquals(await countAll(), 115);
});
}
}

0 comments on commit 2082c0c

Please sign in to comment.