feat: harden analytics dashboard

This commit is contained in:
2026-05-27 15:19:31 +08:00
parent 5e0ca6a504
commit 356039d9cf
34 changed files with 1424 additions and 879 deletions

51
lib/query-cache.test.ts Normal file
View File

@@ -0,0 +1,51 @@
import { describe, expect, test } from "bun:test";
import { createQueryCache } from "./query-cache";
describe("query cache", () => {
test("returns cached values inside TTL", async () => {
let now = 1_000;
const cache = createQueryCache({ ttlMs: 100, maxEntries: 10, now: () => now });
let calls = 0;
const first = await cache.cached("key", async () => {
calls += 1;
return { value: "first" };
});
now += 50;
const second = await cache.cached("key", async () => {
calls += 1;
return { value: "second" };
});
expect(first).toEqual({ value: "first" });
expect(second).toEqual({ value: "first" });
expect(calls).toBe(1);
});
test("refreshes expired values", async () => {
let now = 1_000;
const cache = createQueryCache({ ttlMs: 100, maxEntries: 10, now: () => now });
await cache.cached("key", async () => "first");
now += 101;
const second = await cache.cached("key", async () => "second");
expect(second).toBe("second");
});
test("evicts oldest entries beyond max size", async () => {
const cache = createQueryCache({ ttlMs: 1_000, maxEntries: 2, now: () => 1_000 });
let calls = 0;
await cache.cached("a", async () => "a");
await cache.cached("b", async () => "b");
await cache.cached("c", async () => "c");
const value = await cache.cached("a", async () => {
calls += 1;
return "new-a";
});
expect(value).toBe("new-a");
expect(calls).toBe(1);
});
});