Skip to content

DEV-1685 follow-up: never USE :5432 for the local server either (CodeRabbit) - #91

Merged
ZmeiGorynych merged 1 commit into
mainfrom
egor/dev-1685-local-postgres-provisioner-auto-select-a-free-port-so-the
Aug 11, 2026
Merged

DEV-1685 follow-up: never USE :5432 for the local server either (CodeRabbit)#91
ZmeiGorynych merged 1 commit into
mainfrom
egor/dev-1685-local-postgres-provisioner-auto-select-a-free-port-so-the

Conversation

@ZmeiGorynych

Copy link
Copy Markdown
Member

Follow-up to #90 (already merged) addressing two CodeRabbit "Comments failed to post" findings that were missed on the first pass — both enforce DEV-1685's core invariant that the self-hosted local server never touches the reserved :5432 (IAP tunnel).

  • scripts/build_local_otf_cache.sh: defaulted PGPORT to :5432. Part B (this ticket) removed the only reason it was pinned there — the OTF cache fingerprint no longer embeds host:port:user — so it now just collides with the tunnel. Default to :5435 (which the script's own usage doc already claims); PGPORT still overridable.
  • local_postgres.py::resolve_port: adopted a running cluster's port before checking _RESERVED_PORTS, so a legacy .local_pg cluster on :5432 would be adopted and exported into BIRD_PG_*, colliding with the tunnel. Now hard-fails on a reserved running port and requires a stop+migrate. Regression test added (test_resolve_port_rejects_reserved_running_cluster).

Helper + provision test suites green (38 passed).

🤖 Generated with Claude Code

Two 'comments failed to post' findings CodeRabbit could not attach inline (I
had missed that section on the first pass):

- build_local_otf_cache.sh defaulted PGPORT to :5432. Part B removed the only
  reason it was 5432 (OTF fingerprint parity), so it now just collides with the
  IAP tunnel. Default to :5435 (matching the script's own usage doc); PGPORT
  still overridable.
- resolve_port() adopted a running cluster's port before checking
  _RESERVED_PORTS, so a legacy .local_pg cluster on :5432 would be adopted and
  exported, colliding with the tunnel. Now hard-fail on a reserved running port
  and require a stop+migrate. Regression test added.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@linear

linear Bot commented Jul 17, 2026

Copy link
Copy Markdown
DEV-1685 Local postgres provisioner: auto-select a free port so the IAP tunnel can own :5432

Context

Opening a gcloud compute start-iap-tunnel to a remote PostgreSQL and mapping it to local 127.0.0.1:5432 fails:

bind [127.0.0.1]:5432: Address already in use

:5432 is held by the machine's default system PostgreSQL 16 (postgresql@16-main.service), which the bird-agents benchmark does not use (locally it runs its own sudo-free cluster — see bird-agents/CLAUDE.md → "Running a postgres benchmark LOCALLY").

Decisions:

  • Permanently disable the default system instance (ops, needs sudo) to free :5432.
  • The IAP tunnel keeps :5432, so the benchmark's default BIRD_PG_PORT (5432, db_connection.py) connects to the remote DB through the tunnel with no env change.
  • The benchmark's own self-hosted postgres must come up on another port when needed — never collide with the tunnel (or a stray process) on its target port; pick the next free port automatically instead of failing with a cryptic pg_ctl bind error.

Ops (out of scope for code, done by operator)

sudo systemctl stop  postgresql@16-main postgresql
sudo systemctl disable postgresql@16-main postgresql

Code — auto-port the local provisioner

scripts/run_local_postgres.py and scripts/setup_local_postgres.py must bring the private cluster up on the next free port when the target port (--pg-port/--port, default 5544, or a BIRD_PG_PORT override) is occupied. The actually-chosen port must flow into env_exports so the harness connects to the right place.

  1. New pure helpers in setup_local_postgres.py (add import socket):
    • _port_available(port, host="127.0.0.1") -> bool — TCP bind probe.
    • resolve_port(preferred, running_port) -> int — adopt running cluster's port if up; else scan preferred..preferred+64 for the first free port; SystemExit if none.
    • running_cluster_port(bindir) -> int | None.
  2. setup_local_postgres.main() — resolve the port after _resolve_bindir(), log when it changes, and thread the resolved port through start_cluster / ensure_roles / load_databases / write_env / env_exports. Keep the existing start_cluster mismatch guard.
  3. run_local_postgres.main() — same resolution before slp.start_cluster; use the resolved port in provisioning + os.environ.update(slp.env_exports(...)).
  4. Tests in tests/scripts/test_local_postgres_helpers.py_port_available (bind a real socket), resolve_port (running set → verbatim; preferred busy → next free; preferred free → unchanged), running_cluster_port.
  5. Doc note in bird-agents/CLAUDE.md "Running a postgres benchmark LOCALLY".

No change to db_connection.py (already reads BIRD_PG_HOST/PORT from env).

Verification

  • pytest tests/scripts/test_local_postgres_helpers.py + full non-integration suite (per CLAUDE.md).
  • Manual: with a listener on :5432, setup_local_postgres.py --benchmark livesqlbench-large --port 5432 logs port 5432 busy; using free port 5433, starts there, and .local_pg/env.sh shows BIRD_PG_PORT=5433.

Branched off egor/dev-1668-bird-agents-adopt-unified-inspect-drop-models_summary (the head branch of PR #86).

Review in Linear

@ZmeiGorynych
ZmeiGorynych changed the base branch from egor/dev-1668-bird-agents-adopt-unified-inspect-drop-models_summary to main August 11, 2026 15:36
@ZmeiGorynych
ZmeiGorynych merged commit 7717cb9 into main Aug 11, 2026
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.

1 participant