Skip to content

Commit 6834abd

Browse files
fix(ci): require N consecutive HTTP successes in wait-for-grpc.sh (#63)
Observed flake: probe returns HTTP 200 once on the first attempt that clears the connection-refused phase, exits, tests start, ALL tests fail with 'TypeError: Failed to fetch' to the gRPC backend. The single-probe gate isn't strict enough — a one-shot 200 (e.g. tonic-health responding before the rest of the dispatcher is fully wired) currently passes. Upgrade the readiness signal to N consecutive HTTP successes spaced PROBE_INTERVAL apart (defaults: 3 successes, 0.5s apart), so the probe only declares the server ready after ~1s of demonstrably-stable response. Any non-success in the streak resets it to zero and the slow-poll loop resumes — so a momentary blip during init doesn't get counted twice on either side. Tracked occurrences across recent PR runs: web-sdk PR #23 ci-shard-4, PR #29 ci-shard-1 + ci-shard-4, PR #27 multiple shards.
1 parent c1af231 commit 6834abd

1 file changed

Lines changed: 28 additions & 2 deletions

File tree

scripts/wait-for-grpc.sh

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,27 @@ set -uo pipefail
3434
# and false-positived on a curl edge case that emitted "000000" (likely
3535
# an internal connection retry concatenating two failure codes). The
3636
# regex form is the strict version.
37+
#
38+
# Stability requirement: a single HTTP success isn't enough. Observed
39+
# flake mode: probe gets HTTP 200 once, exits, tests start, ALL tests
40+
# fail with `TypeError: Failed to fetch`. The HTTP layer can flicker up
41+
# briefly during init (e.g. a tonic-health endpoint comes online before
42+
# the rest of the dispatcher is fully wired). We require N consecutive
43+
# successes spaced ~PROBE_INTERVAL apart so a one-shot 200 doesn't pass
44+
# the gate. If the server flickers down between successes, the streak
45+
# resets to zero and the slow-poll loop resumes.
3746

3847
BINARY="${1:?usage: $0 <binary> <port> [log-file] [timeout-seconds]}"
3948
PORT="${2:?usage: $0 <binary> <port> [log-file] [timeout-seconds]}"
4049
LOG_FILE="${3:-/tmp/$(basename "$BINARY").log}"
4150
TIMEOUT="${4:-90}"
4251

52+
# Tunables. Conservative defaults — three consecutive successes 500ms
53+
# apart equals ~1s of stable response, which empirically clears the
54+
# observed flicker window.
55+
REQUIRED_STREAK=3
56+
PROBE_INTERVAL=0.5
57+
4358
chmod +x "$BINARY"
4459
rm -f "$LOG_FILE"
4560

@@ -48,6 +63,7 @@ BIN_PID=$!
4863

4964
deadline=$((SECONDS + TIMEOUT))
5065
attempt=0
66+
streak=0
5167
while true; do
5268
attempt=$((attempt + 1))
5369

@@ -57,10 +73,20 @@ while true; do
5773
# Any 1xx/2xx/3xx/4xx/5xx HTTP code = the server's HTTP layer is up.
5874
# Connection failures and timeouts produce "000" (or empty); we retry.
5975
if [[ "$http_code" =~ ^[1-5][0-9][0-9]$ ]]; then
60-
echo "$(basename "$BINARY") gRPC dispatch responsive after ${attempt} attempt(s) (HTTP $http_code on port $PORT)"
61-
break
76+
streak=$((streak + 1))
77+
if [ "$streak" -ge "$REQUIRED_STREAK" ]; then
78+
echo "$(basename "$BINARY") gRPC dispatch stable after ${attempt} probe(s), ${REQUIRED_STREAK} consecutive HTTP successes (last code $http_code on port $PORT)"
79+
break
80+
fi
81+
# Quick re-probe to confirm the streak.
82+
sleep "$PROBE_INTERVAL"
83+
continue
6284
fi
6385

86+
# Non-success → reset streak. A single bad probe in the middle of a
87+
# would-be confirmation invalidates it — we want N IN A ROW.
88+
streak=0
89+
6490
if [ "$SECONDS" -ge "$deadline" ]; then
6591
echo "::error::$(basename "$BINARY") did not respond on port $PORT within ${TIMEOUT}s (last http_code='$http_code')"
6692
echo "--- $LOG_FILE tail ---"

0 commit comments

Comments
 (0)