Skip to content

Fix flaky test_trigger_log by polling for the status log lines - #73759

Closed
shahar1 wants to merge 1 commit into
apache:mainfrom
shahar1:fix-flaky-test-trigger-log
Closed

shahar1 wants to merge 1 commit into
apache:mainfrom
shahar1:fix-flaky-test-trigger-log

Conversation

@shahar1

@shahar1 shahar1 commented Sep 26, 2026

Copy link
Copy Markdown
Contributor

related: #73397

This PR fixes the flaky test test_trigger_log: the loop now breaks as soon as both status lines arrive, and the upper bound is raised to 300 attempts (30 seconds) so a slow CI runner has enough headroom.

AI Summary `test_trigger_log` gave the forked trigger runner a fixed budget of thirty `_service_subprocess(0.1)` calls before asserting on the "triggers currently running" / "watchers currently running" log lines. `_service_subprocess` returns as soon as any I/O arrives, so on a loaded CI runner that budget can be spent before the runner process has reached its status log. Example failure on an unrelated PR: https://github.com/apache/airflow/actions/runs/36232920075/job/108381612308

This polls until both lines have arrived (up to 300 iterations), mirroring the approach already used by test_trigger_logger_fd_closed_when_removed, and moves the supervisor kill() into a finally block so a failing assertion no longer leaks the runner process.

Follow-up to #73397, which fixed the same class of flakiness in test_trigger_lifecycle.

Verified locally: test_trigger_log passes on repeated runs; prek run --from-ref upstream/main --stage pre-commit passes.


Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Fable 5.1)

Generated-by: Claude Code (Fable 5.1) following the guidelines

The test gave the forked trigger runner a fixed budget of thirty
_service_subprocess(0.1) calls before asserting on the status log lines.
_service_subprocess returns as soon as any I/O arrives, so on a loaded CI
runner that budget can be spent before the runner process has reached its
status log, which made the test fail intermittently on unrelated PRs.

Poll until both lines have arrived, the same way
test_trigger_logger_fd_closed_when_removed already does, and always kill
the supervisor even when the assertion fails.

@subhramit subhramit 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.

Looks good!

@Eason09053360 Eason09053360 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.

I am not sure which are suitable here.
I found #72919 proposed the same fix on Sep 11 (poll up to 300 iterations with an early break, and kill() in finally). It was closed by the one-time open PR limit sweep, not after a review. Its description might goes a bit further on the root cause: the test patches time.monotonic with itertools.count(step=60), the runner is started with os.fork() and inherits that patch, and its "async thread was blocked" watchdog then logs nonstop ahead of the status lines. It also links five more failing runs.

@shahar1

shahar1 commented Sep 26, 2026

Copy link
Copy Markdown
Contributor Author

I am not sure which are suitable here.
I found #72919 proposed the same fix on Sep 11 (poll up to 300 iterations with an early break, and kill() in finally). It was closed by the one-time open PR limit sweep, not after a review. Its description might goes a bit further on the root cause: the test patches time.monotonic with itertools.count(step=60), the runner is started with os.fork() and inherits that patch, and its "async thread was blocked" watchdog then logs nonstop ahead of the status lines. It also links five more failing runs.

Didn't notice this one, thanks for pointing out!
I will close mine in favor of it :)

@shahar1 shahar1 closed this Sep 26, 2026
(FileDeleteTrigger("/tmp/foo.txt", poke_interval=1), 1, 0),
],
)
@patch("time.monotonic", side_effect=itertools.count(start=1, step=60))

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.

If watchdog lines are the only real problem, and status lines are the ones we want, cant we just put a very large threshold, as watchdog logs only when time_elapsed > blocked_main_thread_warning_threshold?

Suggested change
@conf_vars({("triggerer", "blocked_main_thread_warning_threshold"): "1e12"})
@patch("time.monotonic", side_effect=itertools.count(start=1, step=60))

That would stop the flood at the source

@FrankYang0529 FrankYang0529 Sep 27, 2026 •

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.

Thanks for the suggestion. I checked it against the two failure messages we see on CI, and the threshold would only fix one of them.

The threshold would make the logs quieter, but it would not change whether the test passes. I'd prefer to keep this PR as it is.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants