This is an automated email from the ASF dual-hosted git repository.
potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new d4e22155cb0 Fix flaky FileTrigger/FileDeleteTrigger tests by awaiting
the task (#66825)
d4e22155cb0 is described below
commit d4e22155cb0bfe56f2602aee039206a9210f6186
Author: Jarek Potiuk <[email protected]>
AuthorDate: Sun May 17 16:25:03 2026 +0200
Fix flaky FileTrigger/FileDeleteTrigger tests by awaiting the task (#66825)
`test_task_file_trigger` and `test_file_delete_trigger` waited
`asyncio.sleep(0.5)` after `p.touch()` and then asserted on the
trigger's effect (task.done() / file gone). The trigger has to wake
from its poll-interval sleep, run `is_file()`, run `stat()`, (for the
delete variant) run `unlink()`, log, and yield. With anyio's thread-
pool-backed file ops, 0.5s isn't always enough on slow runners — the
Pendulum2 ARM job repeatedly hits the race in `test_file_delete_trigger`
("Found file" is logged but unlink hasn't returned by the time the
assertion runs).
Switch to `await asyncio.wait_for(task, timeout=5.0)` so the assertion
can't race the trigger's detect → yield cycle. Once the task is done,
the trigger has completed all its work (including unlink for the
delete trigger), so the file-existence assertion is deterministic.
Also drop the `asyncio.get_event_loop().stop()` cleanup line. It was
protecting against the pending task left behind by the fixed-sleep
pattern; with `wait_for`, there's no pending task and pytest-asyncio's
own teardown handles loop lifecycle.
---
.../standard/tests/unit/standard/triggers/test_file.py | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/providers/standard/tests/unit/standard/triggers/test_file.py
b/providers/standard/tests/unit/standard/triggers/test_file.py
index 2d5a52eaf15..793f0aeb628 100644
--- a/providers/standard/tests/unit/standard/triggers/test_file.py
+++ b/providers/standard/tests/unit/standard/triggers/test_file.py
@@ -60,12 +60,11 @@ class TestFileTrigger:
p.touch()
- await asyncio.sleep(0.5)
+ # Await the task directly so the assertion can't race the trigger's
+ # detect → yield cycle on slow runners (ARM, Pendulum2 special job).
+ await asyncio.wait_for(task, timeout=5.0)
assert task.done() is True
- # Prevents error when task is destroyed while in "pending" state
- asyncio.get_event_loop().stop()
-
@pytest.mark.skipif(not AIRFLOW_V_3_0_PLUS, reason="Skip on Airflow < 3.0")
class TestFileDeleteTrigger:
@@ -101,8 +100,9 @@ class TestFileDeleteTrigger:
p.touch()
- await asyncio.sleep(0.5)
+ # Await the task directly so the assertion can't race the trigger's
+ # detect → unlink → yield cycle on slow runners (ARM, Pendulum2
+ # special job). The trigger only yields after `await filepath.unlink()`
+ # returns, so once the task is done, the file is guaranteed gone.
+ await asyncio.wait_for(task, timeout=5.0)
assert await anyio.Path(p).exists() is False
-
- # Prevents error when task is destroyed while in "pending" state
- asyncio.get_event_loop().stop()