Skip to content

Commit 15c5c54

Browse files
committed
CLDSRV-992: Wait for a mongo primary before waiting for the S3 API
The mongodb-backed jobs start `docker compose up -d` and then immediately wait up to 40s for port 8000. Nothing waits for MongoDB, and cloudserver's start-up blocks on reaching its metadata backend, so a slow or not-yet-elected mongo does not surface as a mongo error: it surfaces as the S3 API never binding 8000, and the job dies on "Server did not start in less than 40 seconds" with no indication of why. A TCP check on 27018 would not be enough. mongo-run.sh starts mongod straight away but backgrounds rs.initiate() behind a `sleep 5`, so the port answers at least five seconds before the replica set exists. Gate on an elected primary instead -- rs.status().myState == 1 -- which is the condition cloudserver actually needs. The margin is thin even when everything is healthy. On the multiple-backend job the API bound 8000 at t+19.4s on a passing attempt, against a 40s budget that also has to cover image pull, container create and the replica-set init above. A runner half as fast fails, which matches the observed pattern of a job that fails at the port wait and passes on re-run. Applied to the four jobs that run with S3METADATA=mongodb and previously waited only on 8000: multiple-backend, mongo-v0-ft-tests, mongo-v1-ft-tests and sur-tests. A healthy run pays nothing, since the wait returns as soon as a primary is reported. On timeout it dumps rs.status(), so the next occurrence names the real culprit instead of blaming the S3 API. The failing attempt's own server log is no longer available to confirm this directly: the artifacts bundle is per run, so the successful re-run overwrote it. What the surviving log does establish is the 19.4s bind and that mongo is un-gated. Treat this as the probable cause rather than a proven one. Clears CLDSRV-992 row F5 (run 33639273186). Issue: CLDSRV-992
1 parent 4628dd2 commit 15c5c54

2 files changed

Lines changed: 49 additions & 0 deletions

File tree

.github/workflows/tests.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,8 @@ jobs:
336336
- name: Run multiple backend test
337337
run: |-
338338
set -o pipefail;
339+
# start-up blocks on mongo, so a slow mongo looks like 8000 never binding
340+
bash wait_for_mongo_primary.bash 120
339341
bash wait_for_local_port.bash 8000 40
340342
bash wait_for_local_port.bash 81 40
341343
yarn run multiple_backend_test | tee /tmp/artifacts/${{ github.job }}/tests.log
@@ -398,6 +400,8 @@ jobs:
398400
- name: Run functional tests
399401
run: |-
400402
set -o pipefail;
403+
# start-up blocks on mongo, so a slow mongo looks like 8000 never binding
404+
bash wait_for_mongo_primary.bash 120
401405
bash wait_for_local_port.bash 8000 40
402406
yarn run ft_test | tee /tmp/artifacts/${{ github.job }}/tests.log
403407
env:
@@ -459,6 +463,8 @@ jobs:
459463
- name: Run functional tests
460464
run: |-
461465
set -o pipefail;
466+
# start-up blocks on mongo, so a slow mongo looks like 8000 never binding
467+
bash wait_for_mongo_primary.bash 120
462468
bash wait_for_local_port.bash 8000 40
463469
yarn run ft_test | tee /tmp/artifacts/${{ github.job }}/tests.log
464470
yarn run ft_mixed_bucket_format_version | tee /tmp/artifacts/${{ github.job }}/mixed-tests.log
@@ -771,6 +777,8 @@ jobs:
771777
- name: Run SUR-related tests
772778
run: |-
773779
set -ex -o pipefail;
780+
# start-up blocks on mongo, so a slow mongo looks like 8000 never binding
781+
bash wait_for_mongo_primary.bash 120
774782
bash wait_for_local_port.bash 8000 40
775783
yarn run test_sur | tee /tmp/artifacts/${{ github.job }}/tests.log
776784
- name: Cleanup and upload coverage

wait_for_mongo_primary.bash

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#!/usr/bin/env bash
2+
# Wait until the mongo replica set has elected a primary.
3+
#
4+
# mongo-run.sh starts mongod immediately but backgrounds rs.initiate() behind a
5+
# `sleep 5`, so the port answers well before the set exists. A TCP check
6+
# therefore lets tests start against a mongo with no primary, and cloudserver,
7+
# which blocks on its metadata backend during start-up, then never binds 8000.
8+
#
9+
# usage: wait_for_mongo_primary.bash [timeout_seconds]
10+
set -uo pipefail
11+
12+
timeout=${1:-120}
13+
count=0
14+
15+
# compose was brought up from .github/docker, so resolve the project from there
16+
cd "$(dirname "$0")/.github/docker" || exit 1
17+
18+
mongo_state() {
19+
docker compose exec -T mongo \
20+
mongo --port 27018 --quiet --eval 'rs.status().myState' 2>/dev/null \
21+
| tr -dc '0-9'
22+
}
23+
24+
echo "waiting for mongo replica set primary"
25+
while [ "$count" -lt "$timeout" ]; do
26+
# myState 1 is PRIMARY; anything else, or a failed exec, means not ready
27+
if [ "$(mongo_state)" = "1" ]; then
28+
echo ""
29+
echo "Mongo primary ready in ~${count} seconds. Starting test now..."
30+
exit 0
31+
fi
32+
echo -n .
33+
sleep 1
34+
count=$((count + 1))
35+
done
36+
37+
echo ""
38+
echo "Mongo replica set had no primary after ${timeout} seconds. Exiting..."
39+
docker compose exec -T mongo \
40+
mongo --port 27018 --quiet --eval 'rs.status()' 2>&1 | tail -30 || true
41+
exit 1

0 commit comments

Comments
 (0)