fix(migrations): run bootstrap housekeeping on the migrator's held connection#9970
Conversation
|
Claude finished @rubenfiszel's task in 1m 15s —— View job ReviewGood to merge I traced the change through What the fix does correctly
Notes (non-blocking)
Test coverageBackend-only change to the migration-bootstrap path. This is executor-routing refactor of existing SQL, and the migration bootstrap runs on every startup, so the existing startup path exercises it — no new unit test is warranted, and the codebase has no harness for a single-connection-pool migration scenario. The PR's manual verification (default multi-connection boot, |
Pi ReviewGood to merge — clean, well-scoped fix. No blocking issues or nits. What's happeningThe PR prevents a self-deadlock during startup migration bootstrap on single-connection Postgres backends. Two call sites ( The fix exposes the migrator's already-checked-out Things I checked
Test coverageBackend-only change touching migration bootstrap connection routing. The existing migration integration tests cover the normal multi-connection path. The PR description documents manual testing against three single-connection configurations (pool capped at 1, embedded pglite/oliphaunt, and default multi-connection). No new automated tests expected for connection-routing logic. Manual verification needed before merge: none beyond what's already documented in the PR test plan — the tested scenarios (single-connection boot + script/flow execution) directly exercise the deadlock surface this PR removes. |
…nnection migrate() and fix_flow_versioning_migration re-acquired a second connection from the pool while already holding one (the migrator's checked-out, advisory-locked connection). That deadlocks any backend limited to one connection at a time — connection-constrained managed Postgres, PgBouncer transaction pooling, or an embedded single-connection dev database. Route those housekeeping queries onto the already-held connection via a new CustomMigrator::connection() accessor. Fewer connections during migration and, for fix_flow_versioning, the existence check and write now run on the same advisory-locked connection. Default multi-connection behavior is unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
7ec9278 to
54ce0c4
Compare
Pi ReviewGood to merge — no changes since the prior Pi review on this same commit, and the analysis below confirms the earlier verdict. What changedThe PR prevents a self-deadlock during startup migration bootstrap on single-connection Postgres backends (embedded pglite, PgBouncer tx-pooling, tight
The fix exposes the migrator's already-checked-out Re-verified items
Test coverageBackend-only change to migration-bootstrap connection routing. The migration bootstrap runs on every startup, so the existing startup path exercises it. The codebase has no harness for a single-connection-pool migration scenario, and no new unit test is warranted for executor-routing refactoring of unchanged SQL. The PR's documented manual verification (default multi-connection boot, |
Codex ReviewGood to merge. No issues found. Checked for bugs, security, public-surface concerns, AGENTS.md compliance, and prior PR discussion. Test coverageBackend-only migration-bootstrap change. I did not run automated tests for this read-only review. The PR’s documented manual coverage targets the relevant scenarios: normal multi-connection startup and single-connection migration startup. There is no in-app surface to exercise. |
Summary
During startup,
migrate()andfix_flow_versioning_migrationre-acquired a second connection from the pool while already holding one — the connection the migrator has checked out (and holds the migration advisory lock on). That's a self-deadlock against any backend limited to one connection at a time:max_connections),The runtime itself is fine on a single connection; this was purely a migration-bootstrap issue.
Fix
Add a
CustomMigrator::connection()accessor that exposes the already-checked-out connection, and route the migration-phase housekeeping onto it instead of re-acquiring from the pool:windmill-api/src/db.rs— the twoDELETE … _sqlx_migrationshousekeeping queries inmigrate()now run oncustom_migrator.connection().windmill-api/src/live_migrations.rs—fix_flow_versioning_migrationruns its existence check and its transaction on the migrator's connection (drops the now-unused pool parameter).This reduces connection usage during migration, and for
fix_flow_versioningthe existence check and the write now happen on the same advisory-locked connection (tighter, not looser). Normal multi-connection deployments are unaffected — same SQL, same ordering, just a different (already-held) executor.Test plan
workers_alive,database_healthy=true).DATABASE_CONNECTIONS=1): server+worker boot, a bash script and a 2-step flow complete,pg_stat_activityshows a single connection.Context / experiment that surfaced this: WIN-2130 (#9967).
🤖 Generated with Claude Code
Summary by cubic
Prevent self-deadlock during startup migrations by running bootstrap housekeeping on the migrator’s already-held connection instead of acquiring another. Unblocks single-connection backends (PgBouncer tx-pool, low max_connections, embedded dev DB) with no behavior change for multi-connection deployments; addresses WIN-2130.
Written for commit 54ce0c4. Summary will update on new commits.