48 lines
1.6 KiB
TypeScript
48 lines
1.6 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import { TagCache, responseCache } from "../src/index.ts";
|
|
|
|
describe("@wrnexus/cache", () => {
|
|
test("supports fresh, stale, and tag invalidation", async () => {
|
|
let now = 0;
|
|
const cache = new TagCache<number>({ ttlMs: 10, staleWhileRevalidateMs: 10, clock: () => now });
|
|
cache.set("a", 1, { tags: ["users"] });
|
|
expect(cache.lookup("a").state).toBe("fresh");
|
|
now = 11;
|
|
expect(cache.lookup("a").state).toBe("stale");
|
|
expect(cache.invalidateTag("users")).toBe(1);
|
|
expect(cache.lookup("a").state).toBe("miss");
|
|
});
|
|
|
|
test("deduplicates concurrent loaders", async () => {
|
|
const cache = new TagCache<number>();
|
|
let calls = 0;
|
|
const loader = async () => ++calls;
|
|
const [a, b] = await Promise.all([cache.getOrLoad("x", loader), cache.getOrLoad("x", loader)]);
|
|
expect(a).toBe(1);
|
|
expect(b).toBe(1);
|
|
expect(calls).toBe(1);
|
|
});
|
|
|
|
test("response middleware does not call next twice for stale entries", async () => {
|
|
let now = 0;
|
|
const cache = new TagCache<any>({ ttlMs: 1, staleWhileRevalidateMs: 100, clock: () => now });
|
|
const middleware = responseCache({ cache, ttlMs: 1, staleWhileRevalidateMs: 100 });
|
|
let calls = 0;
|
|
const ctx = {
|
|
req: new Request("https://example.com/a"),
|
|
url: new URL("https://example.com/a"),
|
|
} as any;
|
|
await middleware(ctx, async () => {
|
|
calls++;
|
|
return new Response("one");
|
|
});
|
|
now = 2;
|
|
const stale = await middleware(ctx, async () => {
|
|
calls++;
|
|
return new Response("two");
|
|
});
|
|
expect(await stale.text()).toBe("one");
|
|
expect(calls).toBe(1);
|
|
});
|
|
});
|