Skip to content

fix(integration-tests): gate shared-sidecar mode on a real connection (kills ts-integration flake)#167

Merged
dmealing merged 1 commit into
mainfrom
fix/ts-integration-sidecar-readiness
Jul 4, 2026
Merged

fix(integration-tests): gate shared-sidecar mode on a real connection (kills ts-integration flake)#167
dmealing merged 1 commit into
mainfrom
fix/ts-integration-sidecar-readiness

Conversation

@dmealing

@dmealing dmealing commented Jul 4, 2026

Copy link
Copy Markdown
Member

Problem

The ts integration lane intermittently hung to the scenarios' 60s test timeout on the main push path — twice (the #163 and #165 merges), always the sidecar-backed generated-routes lane (create-201, jsonb-open-bag-roundtrip). The Java sidecar lane has been fine; this was TS-specific.

Root cause

Shared-sidecar mode (startOnSharedPostgres) called admin.connect() immediately with no readiness gate and no client-side connect timeout — unlike the per-container path, which deliberately gates on a real canConnect() because pg_isready (what the CI services: postgres health-check uses) can report success during postgres' first-boot init window. Under CI host contention the sidecar is also transiently slow to accept connections, and with no connect timeout pg's first connection to a not-yet-answering server hangs indefinitely → the scenario burns its full 60s timeout instead of retrying.

Fix

Extend the file's existing readiness pattern to shared mode:

  • waitForSharedReady() polls a short-timeout probe connection until the sidecar truly answers (or a 45s budget — kept under the 60s test timeout so the retry loop can actually succeed and still leave time for CREATE DATABASE + server boot).
  • Every Client now carries connectionTimeoutMillis so a stalled attempt fails fast and is retried rather than hanging.

When healthy, the gate returns on the first probe (~ms) — no behavior change on the happy path. When the sidecar never comes up, it throws a clear error instead of an opaque 60s timeout. The change can only prevent hangs.

Verified

The two previously-flaky lanes (api-contract-generated, api-contract-jsonb) run 23/23 green against a real local sidecar in shared mode.

Follow-up (not in this PR): splitting the ts job into fast/slow lanes like Java would further isolate integration from the fast conformance signal — happy to do that next if wanted.

🤖 Generated with Claude Code

… (kills the ts-integration flake)

The ts integration lane intermittently hung to the scenarios' 60s test timeout
on the main push path (twice: the #163 and #165 merges), always in the
sidecar-backed generated-routes lane (create-201 / jsonb-open-bag-roundtrip).

Root cause: shared-sidecar mode (startOnSharedPostgres) did `admin.connect()`
immediately with NO readiness gate and NO client-side connect timeout — unlike
the per-container path, which deliberately gates on a real `canConnect()` because
`pg_isready` (what the CI `services: postgres` health-check uses) can report
success during postgres' first-boot init window. Under CI host contention the
sidecar is also transiently slow to accept connections. With no connect timeout,
pg's first connection to a not-yet-answering sidecar hangs indefinitely → the
scenario burns its full 60s timeout instead of retrying.

Fix: extend the file's existing readiness pattern to shared mode —
`waitForSharedReady()` polls a real short-timeout probe connection until the
sidecar answers (or a 45s budget, kept under the 60s test timeout so the retry
loop can actually succeed), and every Client now carries connectionTimeoutMillis
so a stalled attempt fails fast and is retried rather than hanging. When the
sidecar is healthy the gate returns on the first probe (~ms); when it never comes
up, it throws a clear error instead of an opaque timeout.

Verified: the two previously-flaky lanes (api-contract-generated,
api-contract-jsonb) run 23/23 green against a real local sidecar in shared mode.
The change can only prevent hangs — no behavior change on the healthy path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ew1XfYSbEAezxjs9opynAe
@dmealing
dmealing merged commit 98645c8 into main Jul 4, 2026
1 check passed
@dmealing
dmealing deleted the fix/ts-integration-sidecar-readiness branch July 4, 2026 16:41
dmealing added a commit that referenced this pull request Jul 4, 2026
… flake) (#169)

gate_conf_ts runs the cli suite via `cd packages/cli && bun test` under bun's
default 5s per-test timeout. The cli tests invoke full `meta`/run() dispatch,
which lazily imports each command's (sometimes heavy: codegen, migrate-ts) module
on first use; on a cold/contended self-hosted runner that first cold-start import
can exceed 5s and flake otherwise-instant exit-code/--format tests (seen twice on
the main push path: help-and-exit and index-format, each failing at ~5001ms while
the whole suite runs in ~1.3s warm). bun does NOT honor bunfig.toml `[test]
timeout` (verified: a 1ms config value had no effect), so the fix is the
`--timeout` CLI flag on the invocation. 30s keeps a genuine hang loud while
removing the timing sensitivity. Same root cause as the sidecar readiness fix
(#167) — tight timeouts tripping under host contention.


Claude-Session: https://claude.ai/code/session_01Ew1XfYSbEAezxjs9opynAe

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
dmealing added a commit that referenced this pull request Jul 4, 2026
Mirrors the java-fast/java-slow split. The ts job ran build+typecheck +
conformance + completeness + docker integration all in one job, so a
docker/sidecar hiccup (or the integration flakiness fixed in #167) failed the
whole ts signal and the fast correctness verdict waited on the slow integration.

Now two parallel jobs:
- ts-fast: build+typecheck, conformance, completeness — the pure-code signal, no
  docker/sidecar.
- ts-slow: build + docker/sidecar integration tests (with the shared PG sidecar).

ci-local.sh grows `--only ts-fast|ts-slow` (+ a build-only gate_ts_build for the
isolated slow lane, since the workspace dist/ is needed for integration and the
fast lane's build already produces it in the umbrella case). `--only ts` and a
plain local run still run both lanes, byte-equivalent to before — no double
build. detect still emits the umbrella token `ts`; both jobs gate on it.

Verified: `--only ts-slow` builds and runs the full integration suite 116/0 green
against a real sidecar; the dry-run lister confirms ts-fast/ts-slow/ts/no-flags
all select the right steps with no duplicate build.


Claude-Session: https://claude.ai/code/session_01Ew1XfYSbEAezxjs9opynAe

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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