Skip to content

[fix] Preserve shared Postgres connection during lint probes - #1555

Closed
flamerged wants to merge 1 commit into
garrytan:masterfrom
flamerged:fix/postgres-module-borrower-disconnect
Closed

flamerged wants to merge 1 commit into
garrytan:masterfrom
flamerged:fix/postgres-module-borrower-disconnect

Conversation

@flamerged

@flamerged flamerged commented May 27, 2026 •

Copy link
Copy Markdown
Contributor

Summary

This fixes a Postgres connection-lifecycle bug where short-lived helper engines could tear down the shared module-level database pool that the main gbrain dream cycle still needed.

In the dream cycle, lint runs early and briefly opens an engine to lift DB-backed content-sanity config. On Postgres, that helper can reuse the existing module-level singleton. Before this change, its disconnect() path always called db.disconnect() for module-mode engines, even when the helper did not create the singleton. That leaves later phases with No database connection / connect() has not been called.

Issue cluster

Fixes #1492.
Fixes #1471.
Fixes #1499.

Those reports converge on the same root cause: an early lint/config helper borrows the shared Postgres module singleton, then disconnects it out from under the still-running dream cycle or worker pool.

This also targets the same Postgres "later phase loses the DB connection after an earlier helper phase ran" symptom cluster reported in #1491, #1515, #1531, #1462, and #1422. I am not marking every adjacent report as auto-closed because some include follow-on error-reporting, worker-startup, idle-timeout, or phase-specific details, but this PR removes the shared-pool teardown bug they converge on.

Related but likely separate: #1426 appears to involve PGLite pending-write lifecycle behavior, so this PR does not claim to fix it. #1404 and #1413 have overlapping connect() has not been called evidence, but their later comments also discuss additional lifecycle paths outside this narrow ownership fix.

Why this matters

This is a small lifecycle fix with high operational impact:

  • Keeps long-running dream cycles from losing their Postgres connection after the lint/config probe.
  • Preserves the existing module-singleton compatibility path for CLI flows.
  • Keeps instance-owned worker pools unchanged.
  • Makes ownership explicit: only the engine that created the module singleton can close it; borrower engines clean up their own routing manager but leave the shared pool alive.

For Postgres users, this turns a whole class of hard-to-diagnose dream-cycle crashes back into stable multi-phase runs without changing query semantics or pool setup.

What changed

  • Added module-singleton ownership tracking to PostgresEngine.
  • Updated disconnect() so module-mode borrowers do not call db.disconnect().
  • Expanded the Postgres disconnect E2E coverage to pin:
    • instance-pool double-disconnect safety,
    • module-borrower disconnect safety,
    • the lint DB-config probe path,
    • module-owner disconnect idempotency.

Validation

  • DATABASE_URL=postgresql://postgres:postgres@127.0.0.1:54322/<scratch-db> bun test test/e2e/postgres-engine-disconnect-idempotency.test.ts
  • bun test test/cli-dream-engine-warn.test.ts test/dream.test.ts
  • bun run typecheck
  • git diff --check
  • git show --check HEAD
  • scripts/check-no-double-retry.sh && scripts/check-batch-audit-site.sh && scripts/check-test-isolation.sh
  • gitleaks dir . --redact --no-banner
  • gitleaks git . --redact --no-banner --log-opts="origin/master..HEAD"
  • CodeRabbit local review: 0 findings
  • Claude Code prompt review: no blockers; low-severity comment/test-context nits addressed

@garrytan

garrytan commented Jun 8, 2026

Copy link
Copy Markdown
Owner

Thanks for this! The Postgres module-singleton / "connect() has not been called" ownership bug was fixed canonically in #1805 (atomic owner-only-disconnect), with follow-ups in #1608 and #1572 — all merged to master. Closing as already-resolved. If you still reproduce after upgrading, please reopen, and thank you for the contribution.

@garrytan garrytan closed this Jun 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants