Skip to content

fix(db): lazy-reconnect module singleton to survive mid-cycle teardown (#1570)#1758

Closed
toilalesondev wants to merge 2 commits into
garrytan:masterfrom
toilalesondev:fix/dream-cycle-db-connection
Closed

fix(db): lazy-reconnect module singleton to survive mid-cycle teardown (#1570)#1758
toilalesondev wants to merge 2 commits into
garrytan:masterfrom
toilalesondev:fix/dream-cycle-db-connection

Conversation

@toilalesondev

Copy link
Copy Markdown

Problem

The dream cycle runs its phases sharing the db.ts module-singleton postgres connection. A mid-cycle callee (a module-style engine disconnect between phases) nulls the singleton, so the later sync and synthesize phases throw No database connection: connect() has not been called and the whole cycle reports partial.

Knock-on effect: partial (well, the failed phases) meant the freshness signal was unreliable, and doctor's cycle_freshness check stayed FAIL ("Source X has never completed a full cycle") because the broken phases dominated the run.

This is the singleton-null bug the disconnect-audit instrumentation in #1570 was added to chase. I captured the culprit by logging full stacks in db.disconnect() during a real gbrain dream --source <id> run (interpreted, unminified): a module-style PostgresEngine.disconnect() fires mid-cycle, nulling sql before sync/synthesize reach getConnection().

Fix

getConnection() now lazily rebuilds the pool from a remembered URL (lastConnectedUrl) instead of throwing when the singleton was torn down earlier in the same process. postgres() opens no socket until the first query, so rebuilding from the synchronous getConnection() path is safe. Extracted buildPool() so connect() and the lazy path share identical options.

This is defensive: it self-heals regardless of which phase drops the connection, without re-plumbing every caller's engine.

Verification

  • gbrain dream --source {helmsman,perfeat-mobile,default} — sync + synthesize now run to completion, exit 0, 0 failed phases (were 2: sync + synthesize).
  • doctor cycle_freshness flips to OK across all 3 sources.
  • 52 connection-resilience tests + 64 chunker tests pass.

Refs #1570.

Two coupled bugs blocked code-callers/code-callees for TypeScript:

1. extractSymbolName (code.ts) didn't descend into variable_declarator, so
   'export const Foo = () => {}' (dominant React/RN form) got symbol_name=null
   and its edges were dropped at the import-file.ts:1100 qualified-name gate.
   Fix: name lexical_declaration/variable_declaration via the declarator's
   name field (exact node.type match — never substring, which would corrupt
   Go's var_declaration etc.).

2. import-file.ts edge writes omitted source_id, so every code_edges_symbol
   row landed source_id=NULL and was invisible to source-scoped reads
   (code-callers/callees with --source). Fix: thread sourceId into the edge
   input (default brain → null, matches unscoped reads).

Also bump EDGE_EXTRACTOR_VERSION_TS to force a re-walk past stale watermarks.

Verified on a real RN/TSX repo: code-callers useTheme → 64 resolved callers
(HeroChip, Chip, Card…), code-callees DiaryScreen → 66. Was 0/0 before.
33 chunker unit tests pass incl. 2 new const-arrow naming pins.
garrytan#1570)

The dream cycle runs phases sharing the db.ts module-singleton connection.
A mid-cycle callee (a module-style engine disconnect between phases) nulled
the singleton, so the later sync + synthesize phases threw 'connect() has
not been called' and the whole cycle reported 'partial' — which in turn
left sources.config.last_full_cycle_at unwritten and doctor's cycle_freshness
permanently FAILing.

Fix: getConnection() now lazily rebuilds the pool from a remembered URL
(lastConnectedUrl) instead of throwing when the singleton was torn down
earlier in the same process. postgres() opens no socket until first query,
so the rebuild is safe from the synchronous getConnection() path. Extracted
buildPool() so connect() and the lazy path share identical pool options.

Verified: gbrain dream --source {helmsman,perfeat-mobile,default} now run
sync + synthesize to completion (exit 0, 0 failed phases); doctor
cycle_freshness flips to OK across all 3 sources. 52 connection-resilience
tests + 64 chunker tests pass.

Refs garrytan#1570 (singleton-null disconnect investigation).
@toilalesondev

Copy link
Copy Markdown
Author

Closing as superseded. Upstream already fixes this exact singleton-null mid-cycle bug (#1570) via two landed commits:

Upstream's caller-side fix is canonical; my lazy-reconnect in getConnection() is redundant. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants