From 55179acbe978ac73cafcabff81281023ad6e01c4 Mon Sep 17 00:00:00 2001 From: Jae-Hyuk-Jang Date: Thu, 3 Sep 2026 14:24:43 +0900 Subject: [PATCH 1/3] Test get() excludes an expired KV entry (#876) WorkersKvStore.get() applies expiry via a metadata.expires field independent of Workers KV's own TTL, but the miniflare-backed integration suite (test/kv.test.ts) only tested that set() with a TTL stores that metadata, not that an expired entry is actually excluded when read through the real KV binding. The mocked unit suite in src/mod.test.ts already covered this (added in #987), but not against the real binding. Changelog: none Assisted-by: Claude Code:claude-sonnet-5 --- packages/cfworkers/test/kv.test.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/cfworkers/test/kv.test.ts b/packages/cfworkers/test/kv.test.ts index 931408e3d..9b018ea2d 100644 --- a/packages/cfworkers/test/kv.test.ts +++ b/packages/cfworkers/test/kv.test.ts @@ -30,6 +30,18 @@ describe("WorkersKvStore", () => { expect(await store.get(["ttl", "test"])).toBe("ttl-value"); }); + it("get() - excludes expired entry", async () => { + const store = new WorkersKvStore(env.KV1); + + await env.KV1.put( + JSON.stringify(["expired", "test"]), + JSON.stringify("stale-value"), + { expirationTtl: 60, metadata: { expires: Date.now() - 1000 } }, + ); + + expect(await store.get(["expired", "test"])).toBeUndefined(); + }); + it("delete()", async () => { const store = new WorkersKvStore(env.KV1); From 69b7c55e8d9af8894b3c11ccf22d298d6df179b3 Mon Sep 17 00:00:00 2001 From: Jae-Hyuk-Jang Date: Thu, 3 Sep 2026 14:32:52 +0900 Subject: [PATCH 2/3] Test get() includes an unexpired KV entry (#876) Complements the previous commit's expired-entry test: verifies that an entry whose metadata.expires is still in the future is returned normally by get(), not just excluded when it isn't. Changelog: none Assisted-by: Claude Code:claude-sonnet-5 --- packages/cfworkers/test/kv.test.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/cfworkers/test/kv.test.ts b/packages/cfworkers/test/kv.test.ts index 9b018ea2d..ae7c21ff2 100644 --- a/packages/cfworkers/test/kv.test.ts +++ b/packages/cfworkers/test/kv.test.ts @@ -36,12 +36,24 @@ describe("WorkersKvStore", () => { await env.KV1.put( JSON.stringify(["expired", "test"]), JSON.stringify("stale-value"), - { expirationTtl: 60, metadata: { expires: Date.now() - 1000 } }, + {expirationTtl: 60, metadata: {expires : Date.now() - 1000}}, ); expect(await store.get(["expired", "test"])).toBeUndefined(); }); + it("get() - includes unexpired entry", async () => { + const store = new WorkersKvStore(env.KV1); + + await env.KV1.put( + JSON.stringify(["fresh", "test"]), + JSON.stringify("live-value"), + { expirationTtl: 60, metadata: { expires: Date.now() + 60_000 }}, + ); + + expect(await store.get(["fresh", "test"])).toBe("live-value"); + }) + it("delete()", async () => { const store = new WorkersKvStore(env.KV1); @@ -73,6 +85,8 @@ describe("WorkersKvStore", () => { expect(entries.some((e) => e.key[1] === "nested")).toBe(true); }); + + it("list() - single element key", async () => { const store = new WorkersKvStore(env.KV1); From 49a86098afc2b7e10780d136dd8d4157f49e6617 Mon Sep 17 00:00:00 2001 From: Jae-Hyuk-Jang Date: Thu, 3 Sep 2026 14:52:25 +0900 Subject: [PATCH 3/3] Test list() excludes expired KV entries (#876) Completes the expiry coverage in test/kv.test.ts: list() applies the same metadata.expires check as get(), skipping both the exact-prefix key and matching children when they're expired. Matches the mocked coverage already in src/mod.test.ts (added in #987), now verified against the real KV binding. Changelog: none Assisted-by: Claude Code:claude-sonnet-5 --- packages/cfworkers/test/kv.test.ts | 31 +++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/packages/cfworkers/test/kv.test.ts b/packages/cfworkers/test/kv.test.ts index ae7c21ff2..e3545fca3 100644 --- a/packages/cfworkers/test/kv.test.ts +++ b/packages/cfworkers/test/kv.test.ts @@ -36,7 +36,7 @@ describe("WorkersKvStore", () => { await env.KV1.put( JSON.stringify(["expired", "test"]), JSON.stringify("stale-value"), - {expirationTtl: 60, metadata: {expires : Date.now() - 1000}}, + { expirationTtl: 60, metadata: { expires: Date.now() - 1000 } }, ); expect(await store.get(["expired", "test"])).toBeUndefined(); @@ -48,11 +48,11 @@ describe("WorkersKvStore", () => { await env.KV1.put( JSON.stringify(["fresh", "test"]), JSON.stringify("live-value"), - { expirationTtl: 60, metadata: { expires: Date.now() + 60_000 }}, + { expirationTtl: 60, metadata: { expires: Date.now() + 60_000 } }, ); expect(await store.get(["fresh", "test"])).toBe("live-value"); - }) + }); it("delete()", async () => { const store = new WorkersKvStore(env.KV1); @@ -85,7 +85,32 @@ describe("WorkersKvStore", () => { expect(entries.some((e) => e.key[1] === "nested")).toBe(true); }); + it("list() - excludes expired entries", async () => { + const store = new WorkersKvStore(env.KV1); + + await env.KV1.put( + JSON.stringify(["expired-list"]), + JSON.stringify("stale-root"), + { expirationTtl: 60, metadata: { expires: Date.now() - 1000 } }, + ); + + await env.KV1.put( + JSON.stringify(["expired-list", "stale"]), + JSON.stringify("stale-child"), + { expirationTtl: 60, metadata: { expires: Date.now() - 1000 } }, + ); + + await store.set(["expired-list", "fresh"], "fresh-child"); + const entries: { key: readonly unknown[]; value: unknown }[] = []; + for await (const entry of store.list(["expired-list"])) { + entries.push({ key: entry.key, value: entry.value }); + } + + expect(entries).toEqual([ + { key: ["expired-list", "fresh"], value: "fresh-child" }, + ]); + }); it("list() - single element key", async () => { const store = new WorkersKvStore(env.KV1);