Skip to content

Commit 78a4a1b

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 78a4a1b

1 file changed

Lines changed: 25 additions & 1 deletion

File tree

temporalio/worker/_workflow_instance.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,8 +461,32 @@ 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(
487+
key=lambda j: j.resolve_activity.seq
488+
)
489+
for job in local_activity_jobs:
466490
self._apply(job)
467491

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

0 commit comments

Comments
 (0)