From f51c630cf0588b07f353d83fee421eae4f79f3c7 Mon Sep 17 00:00:00 2001 From: HAL9000 Date: Fri, 24 Apr 2026 18:48:19 +0000 Subject: [PATCH] fix(test): use _original_sleep in slow executor steps to fix flaky timeout test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test-infrastructure patches asyncio.sleep with a 10 ms cap to speed up retry waits. The two slow-executor Behave step definitions used asyncio.sleep(10) as the "slow" coroutine, which was silently capped to 10 ms — the same duration as the 0.01 s executor timeout — creating a race condition that caused the "Executor times out via thread pool path" and "Executor times out via run_coroutine_threadsafe path" scenarios to fail intermittently. Fix: use asyncio._original_sleep (falling back to asyncio.sleep when the patch is absent) with a 0.5 s delay, which is 50× longer than the timeout and guarantees the timeout always fires before the coroutine completes. --- features/steps/langgraph_graph_coverage_steps.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/features/steps/langgraph_graph_coverage_steps.py b/features/steps/langgraph_graph_coverage_steps.py index baba23bcb..861557149 100644 --- a/features/steps/langgraph_graph_coverage_steps.py +++ b/features/steps/langgraph_graph_coverage_steps.py @@ -709,7 +709,10 @@ def step_prepare_slow_executor_bg_loop(context): context.graph.state_manager.update_state = MagicMock() async def slow_execute(state): - await asyncio.sleep(10) + # Use the original (un-patched) asyncio.sleep so the test-infrastructure + # 10 ms sleep cap does not race with the 0.01 s executor timeout. + _real_sleep = getattr(asyncio, "_original_sleep", asyncio.sleep) + await _real_sleep(0.5) return {"messages": ["never"]} context.graph.nodes["worker"].execute = slow_execute @@ -745,7 +748,10 @@ def step_prepare_slow_executor_tp(context): context.graph.state_manager.update_state = MagicMock() async def slow_execute(state): - await asyncio.sleep(10) + # Use the original (un-patched) asyncio.sleep so the test-infrastructure + # 10 ms sleep cap does not race with the 0.01 s executor timeout. + _real_sleep = getattr(asyncio, "_original_sleep", asyncio.sleep) + await _real_sleep(0.5) return {"messages": ["never"]} context.graph.nodes["worker"].execute = slow_execute