From 301a13748d9719e9e7ef7bc09b0a883c7935bd6c Mon Sep 17 00:00:00 2001 From: Yevgen Polyak Date: Wed, 5 Nov 2025 10:43:06 +1300 Subject: [PATCH 1/4] Make when_all and when_any tasks composable #29 Signed-off-by: evhen14 --- durabletask/task.py | 4 ++++ tests/durabletask/test_task.py | 43 ++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/durabletask/task.py b/durabletask/task.py index 2650bfd..66abc28 100644 --- a/durabletask/task.py +++ b/durabletask/task.py @@ -322,6 +322,8 @@ def on_child_completed(self, task: Task[T]): # The order of the result MUST match the order of the tasks provided to the constructor. self._result = [task.get_result() for task in self._tasks] self._is_complete = True + if self._parent is not None: + self._parent.on_child_completed(self) def get_completed_tasks(self) -> int: return self._completed_tasks @@ -423,6 +425,8 @@ def on_child_completed(self, task: Task): if not self.is_complete: self._is_complete = True self._result = task + if self._parent is not None: + self._parent.on_child_completed(self) def when_all(tasks: list[Task[T]]) -> WhenAllTask[T]: diff --git a/tests/durabletask/test_task.py b/tests/durabletask/test_task.py index 81cc8a2..9b1797f 100644 --- a/tests/durabletask/test_task.py +++ b/tests/durabletask/test_task.py @@ -46,6 +46,49 @@ def test_when_all_happy_path_returns_ordered_results_and_completes_last(): assert all_task.get_result() == ["one", "two", "three"] +def test_when_all_is_composable_with_when_any(): + c1 = task.CompletableTask() + c2 = task.CompletableTask() + + any_task = task.when_any([c1, c2]) + all_task = task.when_all([any_task]) + + assert not any_task.is_complete + assert not all_task.is_complete + + c2.complete("two") + + assert any_task.is_complete + assert all_task.is_complete + + assert all_task.is_complete + + assert all_task.get_result() == [c2] + + +def test_when_any_is_composable_with_when_all(): + c1 = task.CompletableTask() + c2 = task.CompletableTask() + c3 = task.CompletableTask() + + all_task1 = task.when_all([c1, c2]) + all_task2 = task.when_all([c3]) + any_task = task.when_any([all_task1, all_task2]) + + assert not any_task.is_complete + assert not all_task1.is_complete + assert not all_task2.is_complete + + c1.complete("one") + c2.complete("two") + + assert any_task.is_complete + assert all_task1.is_complete + assert not all_task2.is_complete + + assert any_task.get_result() == all_task1 + + def test_when_any_happy_path_returns_winner_task_and_completes_on_first(): a = task.CompletableTask() b = task.CompletableTask() From 1a5793eaaa4b416057550992d05fa05b2638a8cb Mon Sep 17 00:00:00 2001 From: Yevgen Polyak Date: Thu, 6 Nov 2025 10:13:43 +1300 Subject: [PATCH 2/4] Update tests/durabletask/test_task.py Co-authored-by: Albert Callarisa Signed-off-by: Yevgen Polyak --- tests/durabletask/test_task.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/durabletask/test_task.py b/tests/durabletask/test_task.py index 9b1797f..45f90e3 100644 --- a/tests/durabletask/test_task.py +++ b/tests/durabletask/test_task.py @@ -60,9 +60,6 @@ def test_when_all_is_composable_with_when_any(): assert any_task.is_complete assert all_task.is_complete - - assert all_task.is_complete - assert all_task.get_result() == [c2] From fadedba4bb6e42db6310d0ba1341142ba428dd46 Mon Sep 17 00:00:00 2001 From: Yevgen Polyak Date: Thu, 6 Nov 2025 10:13:50 +1300 Subject: [PATCH 3/4] Update tests/durabletask/test_task.py Co-authored-by: Albert Callarisa Signed-off-by: Yevgen Polyak --- tests/durabletask/test_task.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/durabletask/test_task.py b/tests/durabletask/test_task.py index 45f90e3..f7edd0f 100644 --- a/tests/durabletask/test_task.py +++ b/tests/durabletask/test_task.py @@ -77,6 +77,11 @@ def test_when_any_is_composable_with_when_all(): assert not all_task2.is_complete c1.complete("one") + + assert not any_task.is_complete + assert not all_task1.is_complete + assert not all_task2.is_complete + c2.complete("two") assert any_task.is_complete From bd3fdb2ef60ea6a768657fadfd048ecc5335a8db Mon Sep 17 00:00:00 2001 From: Albert Callarisa Date: Thu, 6 Nov 2025 07:28:50 +0100 Subject: [PATCH 4/4] Fix linter Signed-off-by: Albert Callarisa --- tests/durabletask/test_task.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/durabletask/test_task.py b/tests/durabletask/test_task.py index f7edd0f..d8ec88e 100644 --- a/tests/durabletask/test_task.py +++ b/tests/durabletask/test_task.py @@ -77,11 +77,11 @@ def test_when_any_is_composable_with_when_all(): assert not all_task2.is_complete c1.complete("one") - + assert not any_task.is_complete assert not all_task1.is_complete assert not all_task2.is_complete - + c2.complete("two") assert any_task.is_complete