Skip to content

fix(ci): retry databend testcontainers bring-up past the image's metasrv race - #44729

Merged
rusackas merged 2 commits into
masterfrom
ultraset-mh-databend-grpc-2
Sep 28, 2026
Merged

rusackas merged 2 commits into
masterfrom
ultraset-mh-databend-grpc-2

Conversation

@sadpandajoe

Copy link
Copy Markdown
Member

SUMMARY

The testcontainers (databend, 10) job fails intermittently on master — run
36296832911 (2026-09-27, master @ eb2ffa2) and run 34816535396 (2026-09-14),
13 consecutive green nightly runs apart — with:

TimeoutError: Container did not emit logs containing 'listened at 0.0.0.0:8000'
within 120.000 seconds. Container status: running

No specific introducing Superset change identified: tests/testcontainers/db_engine_specs/test_databend.py
has one commit in its whole history (3e13b89, #43502) and is unmodified since.
The root cause is in the image's own entrypoint. In databendlabs/databend
docker/bootstrap.sh — identical at the failing build v1.2.881-ca29960f5c-simd,
at tag v1.2.881, and on main — the entire metasrv readiness gate is a bare
sleep 1:

databend-meta ... --single &>/tmp/std-meta.log &
PROCESSES+=($!)
# wait for meta to be ready
sleep 1
...
databend-query -c "$QUERY_CONFIG_FILE" &>/tmp/std-query.log &
PROCESSES+=($!)
...
wait "${PROCESSES[@]}"

Before metasrv binds its gRPC port it must complete an on-disk data upgrade
(V003 → V004, including sled-tree removal) and single-node leader election.
When that overruns the one second — occasionally, on a loaded runner —
databend-query's single connection attempt is refused (Connection refused (os error 111)), query exits, and nothing restarts it. The closing wait
keeps waiting on the surviving metasrv and log-tail PIDs, so the container
reports running forever while the banner line the wait strategy looks for
can never be emitted.

That rules out widening the wait timeout the way test_db2.py legitimately
needs to: no timeout can make a dead one-shot process re-emit a line. Only a
fresh container can re-run the race, so bring-up is retried up to three times,
stopping each container it gives up on and re-raising the original
TimeoutError once the attempts are exhausted. The comment on START_ATTEMPTS
records the mechanism so this isn't later "fixed" by raising the timeout.

The durable fix belongs upstream — poll the gRPC port instead of sleeping, and
supervise databend-query rather than letting wait mask its death. This keeps
master green in the meantime.

TESTING INSTRUCTIONS

Only the databend testcontainers fixture changes, so:

  1. With a Docker daemon available, run the job's own command:
    SUPERSET_TESTCONTAINERS_STRICT=true pytest -v -m testcontainers ./tests/testcontainers/db_engine_specs/test_databend.py
    Both tests should pass, and on a clean first start the log should show a
    single datafuselabs/databend container (the retry adds no work to the
    happy path).
  2. To see the retry engage, force the race the image loses: start a container
    by hand with a pre-populated V003 meta dir, or throttle its I/O
    (docker run --device-read-bps ...) so metasrv's upgrade overruns
    bootstrap.sh's sleep 1. docker ps -a should show an abandoned
    container removed and a second one started, with the suite still passing.
  3. Trigger the workflow directly — Actions → "Testcontainers" →
    workflow_dispatch — and confirm the databend leg is green.

ADDITIONAL INFORMATION

🤖 Generated with Claude Code

…srv race

The `testcontainers (databend, 10)` job fails intermittently on master --
most recently in run 36296832911 (2026-09-27, master @ eb2ffa2), and
before that in run 34816535396 (2026-09-14) -- with:

    TimeoutError: Container did not emit logs containing
    'listened at 0.0.0.0:8000' within 120.000 seconds.
    Container status: running

The cause is in the image's own entrypoint, not in Superset. In
databendlabs/databend `docker/bootstrap.sh` (identical at the failing build
`v1.2.881-ca29960f5c-simd`, at tag v1.2.881 and on main), the entire
metasrv readiness gate is a bare `sleep 1`:

    databend-meta ... --single &>/tmp/std-meta.log &
    PROCESSES+=($!)
    # wait for meta to be ready
    sleep 1
    ...
    databend-query -c "$QUERY_CONFIG_FILE" &>/tmp/std-query.log &
    PROCESSES+=($!)
    ...
    wait "${PROCESSES[@]}"

Before metasrv binds its gRPC port it must finish an on-disk data upgrade
(V003 -> V004, including sled-tree removal) and single-node leader
election. When that overruns the one second -- occasionally, on a loaded
runner -- databend-query's single connection attempt is refused
(`Connection refused (os error 111)`), query exits, and nothing restarts
it. The closing `wait` keeps waiting on the surviving metasrv and log-tail
PIDs, so the container reports `running` forever while the banner line the
wait strategy looks for can never be emitted.

That rules out widening the wait timeout the way test_db2.py legitimately
needs to: no timeout can make a dead one-shot process re-emit a line. Only
a fresh container can re-run the race, so bring-up is retried up to three
times, stopping each container it gives up on and re-raising the original
TimeoutError once the attempts are exhausted.

The durable fix belongs upstream (poll the gRPC port instead of sleeping,
and supervise databend-query rather than letting `wait` mask its death);
this keeps master green in the meantime.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@sadpandajoe sadpandajoe added the ai:fix-master generated by AI to fix master branch label Sep 27, 2026
@codecov

codecov Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.13%. Comparing base (2e13cfa) to head (4e407e6).

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #44729      +/-   ##
==========================================
- Coverage   81.13%   81.13%   -0.01%     
==========================================
  Files        2956     2956              
  Lines      178453   178453              
  Branches    41345    41345              
==========================================
- Hits       144784   144782       -2     
- Misses      30965    30967       +2     
  Partials     2704     2704              
Flag Coverage Δ
hive 36.77% <ø> (ø)
mysql 55.96% <ø> (ø)
postgres 55.96% <ø> (-0.01%) ⬇️
presto 38.68% <ø> (ø)
python 85.41% <ø> (-0.01%) ⬇️
sqlite 55.69% <ø> (ø)
unit 77.71% <ø> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@bito-code-review bito-code-review Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Agent Run #860174

Actionable Suggestions - 1
  • tests/testcontainers/db_engine_specs/test_databend.py - 1
Review Details
  • Files reviewed - 1 · Commit Range: 5907a32..5907a32
    • tests/testcontainers/db_engine_specs/test_databend.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

Comment on lines +84 to +90
try:
container.start()
break
except TimeoutError:
container.stop()
if attempt == START_ATTEMPTS:
raise

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Container leak on start failure

The try/finally at lines 92-100 only guards the post-loop path, so a non-TimeoutError exception from container.start() (docker daemon error, image pull failure, docker.errors.APIError) propagates out of the loop without container.stop(), leaking the container. Add a broad except Exception: container.stop(); raise alongside the TimeoutError handler.

Code Review Run #860174


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them

container.start() failures other than the metasrv-race TimeoutError
(docker daemon error, image pull failure) previously propagated
without calling container.stop(), leaking the container.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@bito-code-review

bito-code-review Bot commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #6a3b9e

Actionable Suggestions - 0
Additional Suggestions - 1
  • tests/testcontainers/db_engine_specs/test_databend.py - 1
    • Broad exception catch · Line 91-96
      New bare `except Exception:` (lines 91-96) violates BITO.md adaptive rule 10033 (catch specific types). It re-raises so no masking, but sibling fixtures `test_starrocks.py:111` and `test_ydb.py:103` use `except Exception as ex: # noqa: BLE001`. Narrow to the docker/requests exceptions you expect, or add the same `# noqa: BLE001` annotation for consistency.
Review Details
  • Files reviewed - 1 · Commit Range: 5907a32..4e407e6
    • tests/testcontainers/db_engine_specs/test_databend.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@rusackas rusackas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@rusackas
rusackas merged commit 0e688a5 into master Sep 28, 2026
94 checks passed
@rusackas
rusackas deleted the ultraset-mh-databend-grpc-2 branch September 28, 2026 17:42
hainenber pushed a commit that referenced this pull request Sep 29, 2026
…srv race (#44729)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
villebro pushed a commit that referenced this pull request Sep 30, 2026
…srv race (#44729)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
(cherry picked from commit 0e688a5)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai:fix-master generated by AI to fix master branch size/M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Nightly databend testcontainers job intermittently times out waiting for query's listen line

2 participants