From 68ecc4ed42595565c41d71d90368c35faa14c164 Mon Sep 17 00:00:00 2001 From: Ryan Rasti Date: Sat, 15 Aug 2026 14:52:11 -0700 Subject: [PATCH] fix: don't drop the live schema while the poller is still running MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit afterAll DROP SCHEMA raced Bus.#poll: the poll is two queries with a release between them, and they share a pool of max: 1. DROP in that gap made the events SELECT fail; close() → stop() then surfaced it as a suite failure. Stop the poller first and leave leftover schema for the next setupDb beforeAll. Swallow in-flight poll errors once stop() has already flipped #running. --- src/live/bus.ts | 8 +++++++- src/test-helpers.ts | 4 +++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/live/bus.ts b/src/live/bus.ts index 90545a9f..33b00771 100644 --- a/src/live/bus.ts +++ b/src/live/bus.ts @@ -312,7 +312,13 @@ export class Bus { #startLoop(): void { this.#loopPromise = (async () => { while (this.#running) { - await this.#poll(); + try { + await this.#poll(); + } catch (e) { + // stop() flipped #running while a poll was in flight (or the + // schema vanished under us). Shutdown is not a poll failure. + if (this.#running) { throw e; } + } const waiters = this.#oncePolled.splice(0); for (const w of waiters) { w(); diff --git a/src/test-helpers.ts b/src/test-helpers.ts index 063b3833..39e798b6 100644 --- a/src/test-helpers.ts +++ b/src/test-helpers.ts @@ -66,7 +66,9 @@ export const setupDb = (): void => { }); afterAll(async () => { - await conn.execute(sql`DROP SCHEMA IF EXISTS ${db.scopedIdent(schema)} CASCADE`); + // Stop the poller first. Don't DROP SCHEMA here — a concurrent poll + // can race the drop (max: 1 pool, two-query poll). Next beforeAll + // already drops leftover schema. await conn.close(); }); };