Skip to content

Commit 61cbb24

Browse files
committed
fix(replication): Mitigate connection hangs on serverless Postgres
- Adds a 500ms delay after preflight checks to allow the connection pool to release connections before pg_dump is executed. - Sets a 30-second connection timeout (PGCONNECT_TIMEOUT) for all pg_dump and pg_dumpall commands to prevent indefinite hangs.
1 parent 68c3664 commit 61cbb24

4 files changed

Lines changed: 22 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## [5.3.15] - 2025-12-03
6+
7+
### Fixed
8+
9+
- **Fix connection hang during preflight checks for SerenDB/Neon targets**: A 500ms delay was added after preflight checks and before any `pg_dump` operations. This allows the connection pool to clean up connections opened during preflight, preventing connection exhaustion that would cause `pg_dumpall` to hang indefinitely on serverless PostgreSQL providers with strict connection limits.
10+
- **Mitigate connection pool exhaustion hangs with timeout**: All `pg_dump` and `pg_dumpall` commands now execute with a 30-second connection timeout (`PGCONNECT_TIMEOUT=30`). This prevents indefinite hangs if the connection pool is exhausted and makes failures detectable instead of causing silent hangs.
11+
512
## [5.3.14] - 2025-12-03
613

714
### Fixed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/commands/init.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,11 @@ pub async fn init(
212212
.context("Source and target validation failed")?;
213213
tracing::info!("✓ Verified source and target are different databases");
214214

215+
// Force connection cleanup before subprocess operations
216+
// Preflight connections should be out of scope, but ensure pool is released
217+
tracing::debug!("Waiting for connection pool cleanup...");
218+
tokio::time::sleep(std::time::Duration::from_millis(500)).await;
219+
215220
// Create managed temporary directory for dump files
216221
// Unlike TempDir, this survives SIGKILL and is cleaned up on next startup
217222
let temp_path =

src/migration/dump.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ pub async fn dump_globals(source_url: &str, output_path: &str) -> Result<()> {
5454
cmd.env(env_var, value);
5555
}
5656

57+
// Set connection timeout to prevent hangs on pool exhaustion
58+
cmd.env("PGCONNECT_TIMEOUT", "30"); // Fail after 30 seconds
59+
5760
cmd.status().context(
5861
"Failed to execute pg_dumpall. Is PostgreSQL client installed?\n\
5962
Install with:\n\
@@ -516,6 +519,9 @@ pub async fn dump_schema(
516519
cmd.env(env_var, value);
517520
}
518521

522+
// Set connection timeout to prevent hangs on pool exhaustion
523+
cmd.env("PGCONNECT_TIMEOUT", "30"); // Fail after 30 seconds
524+
519525
cmd.status().context(
520526
"Failed to execute pg_dump. Is PostgreSQL client installed?\n\
521527
Install with:\n\
@@ -644,6 +650,9 @@ pub async fn dump_data(
644650
cmd.env(env_var, value);
645651
}
646652

653+
// Set connection timeout to prevent hangs on pool exhaustion
654+
cmd.env("PGCONNECT_TIMEOUT", "30"); // Fail after 30 seconds
655+
647656
cmd.status().context(
648657
"Failed to execute pg_dump. Is PostgreSQL client installed?\n\
649658
Install with:\n\

0 commit comments

Comments
 (0)