Fix when_all to wait for all tasks before surfacing failures#173
Open
andystaples wants to merge 5 commits into
Open
Fix when_all to wait for all tasks before surfacing failures#173andystaples wants to merge 5 commits into
andystaples wants to merge 5 commits into
Conversation
when_all previously failed fast on the first child task failure. It now waits for every child task to complete before surfacing the first failure, matching the semantics of .NET's Task.WhenAll.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR adjusts the core task.when_all() composite-task behavior in the Durable Task Python SDK to match .NET Task.WhenAll semantics by waiting for all child tasks to finish before completing and surfacing failures.
Changes:
- Updated
WhenAllTask.on_child_completedto delay completion until every child task finishes, recording the first failure to surface at the end. - Updated the fan-in unit test to assert the orchestration keeps running (no new actions) after an early failure until remaining tasks complete.
- Added an Unreleased changelog entry documenting the behavior change.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
durabletask/task.py |
Updates WhenAllTask completion/failure timing to avoid fail-fast behavior. |
tests/durabletask/test_orchestration_executor.py |
Adjusts test expectations to confirm orchestration remains running until all children complete, then fails. |
CHANGELOG.md |
Documents the when_all() behavioral fix under Unreleased / FIXED. |
berndverst
reviewed
Jul 14, 2026
berndverst
reviewed
Jul 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
task.when_all()previously failed fast: as soon as one of its child tasks failed, the composite task was marked complete and the failure was surfaced immediately, even while sibling tasks were still running.This does not match the .NET SDK (durabletask-dotnet), which relies on the framework's
Task.WhenAll. That contract is: the returned task completes only after all supplied tasks finish, and then surfaces the first fault.This PR changes
WhenAllTask.on_child_completedto record the first exception but only complete once every child task has completed — surfacing the first failure at that point (or building the ordered result list if none failed).Behavior change
An orchestration that fans out and hits a failure now waits for the remaining sibling tasks to finish before failing, instead of failing immediately. This is a deliberate change to match .NET semantics.
Changes
durabletask/task.py—WhenAllTask.on_child_completedno longer sets_is_completeon the first failure; it completes (with the first exception, if any) only after all children complete.tests/durabletask/test_orchestration_executor.py— updatedtest_fan_in_with_single_failureto assert the orchestration keeps running (zero actions) while tasks are outstanding, then fails once all children complete.CHANGELOG.md— added aFIXEDentry.Testing
pytest tests/durabletask/test_orchestration_executor.py— all passflake8clean on changed files