Deploy: make the database wait say why it is failing

On a Synology first run, migrate exited with "postgres:5432 never accepted a
connection" after the full 180s — and that was the entire diagnostic output,
despite the network being demonstrably fine afterwards (postgres resolved and
port 5432 was open from a throwaway container on the same network).

The retry loop caught OSError and discarded it. It now prints the first
failure immediately and repeats every 30s, with the hostname's resolved
address alongside, and includes the last error in the final message. A
DNS failure, a refused connection and a silently dropped packet each produce
a different line instead of the same useless one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nux3LCu4zP9nih4BRhPyHw
This commit is contained in:
2026-09-14 20:48:29 +02:00
co-authored by Claude Opus 5
parent ff64a5dfe7
commit 5c59eecff2
+24 -2
View File
@@ -38,15 +38,37 @@ host = parsed.hostname or "postgres"
port = parsed.port or 5432 port = parsed.port or 5432
deadline = time.time() + float(os.environ.get("DB_WAIT_SECONDS", "180")) deadline = time.time() + float(os.environ.get("DB_WAIT_SECONDS", "180"))
# Report WHY it is not connecting, not just that it isn't: the first failure
# immediately, then every 30s. A silent retry loop that ends in "never accepted"
# tells whoever is installing this precisely nothing.
last_error = None
next_report = 0.0
while time.time() < deadline: while time.time() < deadline:
try: try:
with socket.create_connection((host, port), timeout=3): with socket.create_connection((host, port), timeout=3):
print(f"[entrypoint] database accepting connections at {host}:{port}") print(f"[entrypoint] database accepting connections at {host}:{port}")
sys.exit(0) sys.exit(0)
except OSError: except OSError as exc:
last_error = exc
if time.time() >= next_report:
try:
resolved = socket.gethostbyname(host)
except OSError as dns_exc:
resolved = f"UNRESOLVED ({dns_exc})"
print(
f"[entrypoint] waiting for {host}:{port} "
f"(resolves to {resolved}): {type(exc).__name__}: {exc}",
flush=True,
)
next_report = time.time() + 30
time.sleep(2) time.sleep(2)
print(f"[entrypoint] ERROR: {host}:{port} never accepted a connection", file=sys.stderr) print(
f"[entrypoint] ERROR: {host}:{port} never accepted a connection. "
f"Last error: {type(last_error).__name__}: {last_error}",
file=sys.stderr,
)
sys.exit(1) sys.exit(1)
PYEOF PYEOF
} }