Skip to content

Commit 02e2c5e

Browse files
committed
Fix concurrent local activity replay nondeterminism
During first execution, local activity resolve_activity jobs arrive in completion order (wall-clock). During replay, they arrive in sequence number order. When multiple coroutines issue local activities concurrently, this ordering difference causes coroutines to resume in a different order, assigning different sequence numbers to subsequent commands and triggering NondeterminismError. Fix by sorting local activity resolutions by sequence number before processing. This ensures coroutines always resume in scheduling order regardless of execution mode.
1 parent d5f5d96 commit 02e2c5e

1 file changed

Lines changed: 23 additions & 1 deletion

File tree

temporalio/worker/_workflow_instance.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,8 +461,30 @@ def activate(
461461
for index, job_set in enumerate(job_sets):
462462
if not job_set:
463463
continue
464+
# Separate local-activity resolutions from other jobs.
465+
# Local activity results may arrive in non-deterministic
466+
# order (completion order varies between first-execution
467+
# and replay). Sort them by sequence number so coroutines
468+
# always resume in scheduling order, ensuring deterministic
469+
# interleaving regardless of execution mode.
470+
local_activity_jobs = []
471+
other_jobs = []
464472
for job in job_set:
465-
# Let errors bubble out of these to the caller to fail the task
473+
if (
474+
job.HasField("resolve_activity")
475+
and job.resolve_activity.is_local
476+
):
477+
local_activity_jobs.append(job)
478+
else:
479+
other_jobs.append(job)
480+
481+
# Apply non-local-activity jobs first
482+
for job in other_jobs:
483+
self._apply(job)
484+
485+
# Apply local activity resolutions sorted by seq number.
486+
local_activity_jobs.sort(key=lambda j: j.resolve_activity.seq)
487+
for job in local_activity_jobs:
466488
self._apply(job)
467489

468490
# Run one iteration of the loop. We do not allow conditions to

0 commit comments

Comments
 (0)