From 71be1afbe2be378c3c0f5c6df5d134d0da76a7c0 Mon Sep 17 00:00:00 2001 From: Tony Le Date: Fri, 24 Jul 2026 15:25:58 -0400 Subject: [PATCH] fix(workerchild): ignore empty producer future sets --- .../taskbroker_client/worker/workerchild.py | 2 +- clients/python/tests/worker/test_worker.py | 36 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/clients/python/src/taskbroker_client/worker/workerchild.py b/clients/python/src/taskbroker_client/worker/workerchild.py index 726b4722..4f846ccb 100644 --- a/clients/python/src/taskbroker_client/worker/workerchild.py +++ b/clients/python/src/taskbroker_client/worker/workerchild.py @@ -556,7 +556,7 @@ def check_task_future_completion( if next_state != TASK_ACTIVATION_STATUS_COMPLETE: task_produced_futures = {} - if len(task_produced_futures) == 0: + if not any(task_produced_futures.values()): _task_execution_complete( inflight, next_state, diff --git a/clients/python/tests/worker/test_worker.py b/clients/python/tests/worker/test_worker.py index 7253a74e..f61b1e2f 100644 --- a/clients/python/tests/worker/test_worker.py +++ b/clients/python/tests/worker/test_worker.py @@ -1972,6 +1972,42 @@ def test_child_process_tracks_producer_futures( assert result.status == TASK_ACTIVATION_STATUS_COMPLETE +@pytest.mark.parametrize("producer_cls", _PRODUCER_CLASSES) +def test_child_process_ignores_empty_producer_future_sets( + producer_cls: type, + clear_pending_futures: None, + restore_signal_handlers: None, +) -> None: + task = _producing_task() + todo: queue.Queue[InflightTaskActivation] = queue.Queue() + processed: queue.Queue[ProcessingResult] = queue.Queue() + shutdown = Event() + + todo.put(task) + with ( + mock.patch.object(producer_cls, "collect_futures", return_value={"test.producer": set()}), + mock.patch( + "taskbroker_client.worker.workerchild.ActivationWithPendingFutures" + ) as pending_task, + ): + child_process( + "examples.app:app", + todo, + processed, + shutdown, + max_task_count=1, + processing_pool_name="test", + process_type="fork", + skip_awaiting_futures=False, + future_checking_frequency=0.1, + ) + + pending_task.assert_not_called() + result = processed.get(timeout=5) + assert result.task_id == task.activation.id + assert result.status == TASK_ACTIVATION_STATUS_COMPLETE + + @pytest.mark.parametrize("producer_cls", _PRODUCER_CLASSES) def test_child_process_holds_result_until_futures_done( producer_cls: type,