diff --git a/container/agent-runner/src/db/connection.ts b/container/agent-runner/src/db/connection.ts index 3ca44a8..ac563fa 100644 --- a/container/agent-runner/src/db/connection.ts +++ b/container/agent-runner/src/db/connection.ts @@ -27,6 +27,13 @@ const DEFAULT_HEARTBEAT_PATH = '/workspace/.heartbeat'; let _inbound: Database | null = null; let _outbound: Database | null = null; let _heartbeatPath: string = DEFAULT_HEARTBEAT_PATH; +// True when initTestSessionDb() set _inbound to an in-memory DB. Used by +// openInboundDb() so tests don't try to open the missing /workspace path. +let _inboundIsTest = false; +// Saved real close() for the in-memory inbound singleton. We no-op the +// public .close() during tests so caller try/finally doesn't tear down +// the shared DB; closeSessionDb() invokes this to do the real teardown. +let _inboundOriginalClose: (() => void) | null = null; /** * Avoid all cached db reads; open inbound.db read-only with mmap and page cache disabled. @@ -42,6 +49,12 @@ let _heartbeatPath: string = DEFAULT_HEARTBEAT_PATH; * Cost is microseconds per query, so safe for universal use. */ export function openInboundDb(): Database { + // In test mode the inbound DB is an in-memory singleton — there is no + // file at DEFAULT_INBOUND_PATH. Return the singleton directly; its + // .close() was no-op'd in initTestSessionDb so caller try/finally + // cleanup doesn't tear down the shared DB. + if (_inboundIsTest && _inbound) return _inbound; + const db = new Database(DEFAULT_INBOUND_PATH, { readonly: true }); db.exec('PRAGMA busy_timeout = 5000'); db.exec('PRAGMA mmap_size = 0'); @@ -171,6 +184,12 @@ export function clearStaleProcessingAcks(): void { /** For tests — creates in-memory DBs with the session schemas. */ export function initTestSessionDb(): { inbound: Database; outbound: Database } { _inbound = new Database(':memory:'); + _inboundIsTest = true; + // No-op .close() so callers using openInboundDb()'s try/finally pattern + // don't tear down our shared singleton. closeSessionDb() does the real + // teardown via the saved original. + _inboundOriginalClose = _inbound.close.bind(_inbound); + _inbound.close = () => {}; _inbound.exec('PRAGMA foreign_keys = ON'); _inbound.exec(` CREATE TABLE messages_in ( @@ -244,8 +263,14 @@ export function initTestSessionDb(): { inbound: Database; outbound: Database } { } export function closeSessionDb(): void { - _inbound?.close(); + if (_inboundOriginalClose) { + _inboundOriginalClose(); + _inboundOriginalClose = null; + } else { + _inbound?.close(); + } _inbound = null; + _inboundIsTest = false; _outbound?.close(); _outbound = null; }