Skip to content

when_all hangs when some children complete before when_all is constructed #1149

Description

@passuied

Expected Behavior

yield when_all(children) should complete when all child tasks complete, even if some children finished before when_all(...) was constructed (deferred fan-in).

Common pattern:

children = [ctx.call_child_workflow(...) for ...]
yield ctx.create_timer(...)          # or an activity
yield when_all(children)             # constructed later

Actual Behavior

If some but not all children are already complete when when_all is constructed, when_all never completes. The orchestration hangs until an outer timeout (if any).

Root Cause

In WhenAllTask.__init__:

super().__init__(tasks)       # CompositeTask counts already-complete children
self._completed_tasks = 0     # resets the counter — drops those completions
self._failed_tasks = 0

CompositeTask.__init__ correctly calls on_child_completed for pre-completed children. Resetting the counters afterward loses that count. Later completions only increment from 0, so the total never reaches len(tasks).

Edge cases today:

  • 0 early completions → works
  • all early completions → works (is_complete set before reset)
  • partial early completions → hangs

Steps to Reproduce

from dapr.ext.workflow._durabletask import task

children = [task.CompletableTask() for _ in range(5)]
for child in children[:3]:
    child.complete(None)

all_task = task.when_all(children)
# all_task.get_completed_tasks() == 0  (bug; should be 3)

children[3].complete(None)
children[4].complete(None)
# all_task.is_complete is False forever (bug; should be True)

Observed in production stress testing against dapr-ext-workflow==1.18.1 with deferred when_any([when_all(children), timeout]) after a terminate activity — intermittent depending on how many children finish during the activity.

Release Note

RELEASE NOTE: FIX Bug causing when_all to hang when some child tasks complete before when_all is constructed

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions