App.lock()/unlock() (the HTTP write path — negotiate, complete, and every other request handler, ~210 call sites) now acquire a per-thread connection from a new, separate write_pool instead of blocking on one process-wide conn_mutex guarding one fixed connection. Reentrancy (a handler holding the connection then calling writePublicHtml, which re-acquires it for the nav lookup) is preserved via threadlocal state instead of a global scalar, so nested calls on the same thread reuse the same connection/transaction while different worker threads now genuinely run concurrent DB work instead of serializing. SET statement_timeout='30s' is reissued on every acquire (cheap, idempotent) rather than tracked per physical connection. write_pool is a separate pool instance from db_pool specifically so this doesn't leak the timeout onto db_pool's deliberately-unbounded read connections. Scope turned out much narrower than first planned: background.zig's worker subsystem (TokenGc, SnapshotJob, NotificationJob, TrustJob, ImageJob, ControlJob) and the review agent's detached thread all still hold the original app.conn/app.conn_mutex directly, completely unchanged — they're independent physical connections from the HTTP write path either way (same reasoning that already lets db_pool's read connections run concurrently with everything else), so leaving them alone was both correct and lower-risk than converting them. Verified: full test suite green against both no-PG and a real throwaway Postgres (636/639 pass, same 3 pre-existing failures as the established baseline, nothing new); live-verified on a local daemon — authenticated page loads (which nest a second lock() call for the nav lookup, the exact scenario that caused the original self-deadlock) succeed, 50 concurrent authenticated requests succeed with zero growth in Postgres connection count before/during/after (no leak). Deploy note: doubles baseline Postgres connections (two pools at cfg.postgres.pool_size each, default 16+16); recommend canary-first rollout given this touches the daemon's core concurrency model. Bump to v1.56.211

dev · 5 weeks ago · 2026-07-17 · 15.1 MB

session: phase C write-path connection pool · agent: claude-sonnet-5

$ koh steal kepr.uk/kepr@7f3acb34dafa
·
← 9d31625d47d8 3f9b450c6e78 →
⇓ download .face