Skip to content

fix(ci): give the db2 testcontainer boot real wait headroom - #44399

Open
sadpandajoe wants to merge 2 commits into
masterfrom
ultraset-master-health-db2-timeout
Open

sadpandajoe wants to merge 2 commits into
masterfrom
ultraset-master-health-db2-timeout

Conversation

@sadpandajoe

Copy link
Copy Markdown
Member

SUMMARY

The nightly testcontainers (db2, 25) leg fails intermittently with
TimeoutError: Wait time (120.0s) exceeded for _connect
(run 35185304121).

Root cause. Db2Container._connect (testcontainers 4.15.0,
community/db2/__init__.py:54-56) calls
wait_for_logs(self, predicate="Setup has completed") with no explicit
timeout, so it inherits the library's global default —
max_tries (120) × sleep_time (1s) = 120s
(core/config.py:103-104,160-161). That value is bound as a default
argument
when core/waiting_utils is imported, and Db2Container
exposes no constructor argument to widen it (**kwargs is forwarded to
docker_client.create(), not to the waiter).

A full Db2 instance bring-up varies widely. Across the retained nightly
runs the pytest session for this module measured 88s to 153s end to
end, so a hard 120s cap on the boot wait alone has near-zero margin. In
the failing run the container was still running and had just logged
(*) Creating database testdb ... when the timer expired — a slow boot,
not a broken container or a stale predicate. The 25-minute job budget
is unrelated and was nowhere near binding: that job used 4m02s.

Fix. Attach an explicit wait strategy before starting the container,
matching the idiom already used by test_databend.py, test_monetdb.py,
test_oceanbase.py, test_risingwave.py and test_yugabytedb.py.
DbContainer.start() delegates to DockerContainer.start(), which
honors _wait_strategy (core/container.py:280-286), so this runs to
completion before _connect is called. LogMessageWaitStrategy
searches the full accumulated container.get_logs() with the same
pattern, so _connect then matches on its first poll and its own 120s
window is permanently off the critical path — no library internals are
monkeypatched and no private method is overridden.

Behavior change worth noting: LogMessageWaitStrategy also raises
RuntimeError if the container exits before the message appears
(core/wait_strategies.py:138-150). This is an improvement — a crashed
Db2 now fails fast instead of burning the full timeout — but it is a
change from the previous behavior, which would have waited out the
whole window regardless.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

N/A — not a UI change.

TESTING INSTRUCTIONS

This cannot be verified on Apple Silicon: icr.io/db2_community/db2
publishes no arm64 build. On an x86_64 host with Docker:

uv pip install -e .[db2]
pytest -v -m testcontainers tests/testcontainers/db_engine_specs/test_db2.py

Otherwise, trigger the Testcontainers workflow via workflow_dispatch
on this branch and confirm the testcontainers (db2, 25) leg is green.
Because the failure is an intermittent margin problem (1 failure in the
8 retained nightly runs), a single green run confirms no regression but
not the absence of the original defect; the nightly cron is the real
signal.

No hermetic unit test is possible here — the defect is wall-clock margin
against a real container boot, which needs Docker and a multi-GB image.
The rationale for the 900s value is recorded in a comment in the fixture
in place of the test that cannot be written.

ADDITIONAL INFORMATION

sadpandajoe and others added 2 commits September 17, 2026 05:53
The nightly `testcontainers (db2, 25)` leg fails intermittently with
`Wait time (120.0s) exceeded for _connect`.

`Db2Container._connect` calls `wait_for_logs(self, predicate="Setup has
completed")` with no explicit timeout, so it inherits testcontainers'
global default -- `max_tries` (120) x `sleep_time` (1s) = 120s -- which
is bound as a default argument when `core/waiting_utils` is imported and
is not configurable through `Db2Container`'s constructor.

A full Db2 instance bring-up varies widely. Across the retained nightly
runs, the pytest session for this module measured 88s to 153s end to
end, so a hard 120s cap on the boot wait alone has near-zero margin. In
the failing run the container was still `running` and had just logged
`(*) Creating database testdb ...` when the timer expired -- a slow
boot, not a broken container or a stale predicate. The 25-minute job
budget was never close to binding: that job used 4m02s.

Attach an explicit wait strategy before starting the container, matching
the idiom already used by test_databend.py, test_monetdb.py,
test_oceanbase.py, test_risingwave.py and test_yugabytedb.py.
`DbContainer.start()` delegates to `DockerContainer.start()`, which
honors `_wait_strategy`, so this runs to completion before `_connect` is
called; `_connect` then finds the line already present in the
accumulated logs and returns on its first poll, leaving its own 120s
window permanently off the critical path.

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

bito-code-review Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #63811a

Actionable Suggestions - 0
Additional Suggestions - 1
  • tests/testcontainers/db_engine_specs/test_db2.py - 1
    • Magic timeout literal · Line 70-70
      The 900s startup timeout is a bare magic literal encoding a business threshold (dim 5). The comment documents it well, but a named constant (e.g. `DB2_STARTUP_TIMEOUT = 900`) would make the intent self-describing and give a single place to tune it if the bring-up window changes.
Review Details
  • Files reviewed - 1 · Commit Range: 467d00a..7bfb9c9
    • tests/testcontainers/db_engine_specs/test_db2.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

@codecov

codecov Bot commented Sep 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.41%. Comparing base (77dbaaf) to head (7bfb9c9).

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #44399      +/-   ##
==========================================
- Coverage   80.41%   80.41%   -0.01%     
==========================================
  Files        2932     2932              
  Lines      174621   174621              
  Branches    40559    40559              
==========================================
- Hits       140415   140413       -2     
- Misses      31539    31541       +2     
  Partials     2667     2667              
Flag Coverage Δ
hive 37.33% <ø> (ø)
mysql 56.59% <ø> (ø)
postgres 56.60% <ø> (ø)
presto 39.22% <ø> (ø)
python 84.77% <ø> (-0.01%) ⬇️
sqlite 56.30% <ø> (ø)
unit 76.41% <ø> (-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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Nightly db2 testcontainers job intermittently times out waiting for "Setup has completed"

1 participant