Skip to content

Instantly share code, notes, and snippets.

@nberlette
Last active April 18, 2024 18:43
Show Gist options
  • Save nberlette/5887f207ffd3c57b9cfc6405e6201ea9 to your computer and use it in GitHub Desktop.
Save nberlette/5887f207ffd3c57b9cfc6405e6201ea9 to your computer and use it in GitHub Desktop.
Deno KV: list / search / sort huge batches of entries in database
export interface ListAllOptions<T> extends Deno.KvListOptions {
comparer?(a: Deno.KvEntry<T>, b: Deno.KvEntry<T>): number;
}
export interface ListEntry<T> extends Deno.KvEntry<T> {
readonly cursor: string;
}
export async function listAll<T>(
kv: Deno.Kv,
selector: Deno.KvListSelector,
options?: ListAllOptions<T>,
): Promise<ListEntry<T>[]> {
let { comparer, cursor, ...opts } = {
limit: 1000,
batchSize: 500,
...options
};
comparer ??= defaultComparer;
const results: ListEntry<T>[] = [];
loop: while (true) {
const iter = kv.list<T>(selector, { ...opts, cursor });
const batch: ListEntry<T>[] = [];
for await (const entry of iter) {
cursor = iter.cursor;
batch.push({ ...entry, cursor });
}
results.push(...batch);
if (batch.length) continue loop; break loop;
}
if (typeof comparer === "function") results.sort(comparer);
return results;
}
export function defaultComparer<T>(a: Deno.KvEntry<T>, b: Deno.KvEntry<T>): number {
const { key: keyA, value: _valueA } = a, { key: keyB, value: _valueB } = b;
return (keyA as unknown as unknown[]).reduce<number>((cur, partA, i) => {
const typeA = typeof partA;
const partB = keyB[i];
const typeB = typeof partB;
const acc = Number(cur);
if (partA instanceof Uint8Array && partB instanceof Uint8Array) {
return (partA.length - partB.length) + acc;
} else if (typeA !== typeB) {
return String(partA).localeCompare(String(partB)) + acc
} else if (keyA[i] !== keyB[i]) {
return (keyA[i] > keyB[i] ? 1 : -1) + acc;
} else {
return acc;
}
}, 0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment