clone

nostr relays on demand at <name>.bind.ws: claim one with your key, pay in zaps past the free allowance

test: interrupted promotion checks publication directly because expiry cleanup can remove pending rows

Dami committed 863614a
commit
863614a0e4994b664cf51641d8ff723147a19c98
parent
02be180016c8f7ed4fd05abf9960e3b61a2282d2
author
Dami <dami.etoile@gmail.com>
1 file changed, +16 -2
Mtest/object/grasp.test.ts18++++++++++++++++--
M test/object/grasp.test.ts +16 -2
@@ -422,6 +422,12 @@ describe("GRASP", () => {
422422 const replay = await runInDurableObject(stub, async (relay) => {423423 const bucket = relay.media;424424 let roots = 0;425+ const published: string[] = [];426+ const broadcast = relay.broadcast.bind(relay);427+ Object.defineProperty(relay, "broadcast", { configurable: true, value: (event: Parameters<typeof relay.broadcast>[0]) => {428+ published.push(event.id);429+ broadcast(event);430+ } });425431 const observed = new Proxy(bucket, { get(target, name) {426432 if (name === "get") return (key: string, options?: R2GetOptions) => {427433 // The replay loads the WAL, then promotion loads it again. Change
@@ -443,15 +449,23 @@ describe("GRASP", () => {
443449 body: concat(packet(`${"0".repeat(40)} ${pack.commitID} refs/heads/main\0report-status\n`), flush(), pack.pack),444450 }));445451 expect(roots).toBeGreaterThanOrEqual(2);452+ expect(published).toContain(announcement.id);453+ expect(published).toContain(state.id);454+ expect(published).not.toContain(pr.id);446455 return await response.text();447- } finally { Reflect.deleteProperty(relay, "media"); }456+ } finally {457+ Reflect.deleteProperty(relay, "media");458+ Reflect.deleteProperty(relay, "broadcast");459+ }448460 });449461 expect(replay).toContain("ok refs/heads/main");450462 await runInDurableObject(stub, async (relay) => {451463 const wal = await gitRepository(relay, storedRepository(relay, pk(owner), "promotion")!);452464 expect((await wal.load()).sequence).toBe(1);453465 expect(relay.sql.exec("SELECT id FROM grasp_pending WHERE id IN (?,?)", announcement.id, state.id).toArray()).toEqual([]);454- expect(relay.sql.exec("SELECT id FROM grasp_pending WHERE id=?", pr.id).toArray()).toHaveLength(1);466+ // Expiry cleanup can remove the event and its pending row between467+ // requests. If the event survives, it must still be held from readers.468+ expect(relay.sql.exec("SELECT id FROM events WHERE id=? AND NOT EXISTS (SELECT 1 FROM grasp_pending WHERE grasp_pending.id=events.id)", pr.id).toArray()).toEqual([]);455469 });456470 const reader = await WS.connect(host);457471 expect((await reader.query({ ids: [announcement.id, state.id] })).events).toHaveLength(2);