Skip to content

Preserve pending operations across signal wakeups - #97

Merged
rmcdaniel merged 1 commit into
mainfrom
fix/pending-operation-replay
Oct 7, 2026
Merged

rmcdaniel merged 1 commit into
mainfrom
fix/pending-operation-replay

Conversation

@rmcdaniel

@rmcdaniel rmcdaniel commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

Problem

Addresses #96, delivered in 2.4.1 after published-artifact verification.

A signal waking a workflow with a pending scalar timer, remote activity or child
caused replay to emit that scheduling command again. Server allocated another
operation sequence. Timers acquired a later deadline, and the duplicate result
could collide with the next workflow operation during replay.

Change

  • Validate the pending recorded operation and wait for its result without
    reissuing it. New operations and local activity preparation keep their paths.
  • Include recorded timer delays in replay diagnostics, retaining histories
    without a recorded delay.
  • Add a minimal append-only Avro replay fixture and focused regression coverage
    for repeated signals, fresh worker replay, original completion, changed code,
    legacy history and refusal to hide already duplicated timers.
  • Update older test assertions that expected scalar rescheduling. Their
    cancellation identity, original authority, deadline and policy checks remain.
  • Prepare patch 2.4.1 and document diagnosis of previously affected histories.

Verification

The unmodified published SDK reproduced duplicate timers on published Server
2.5.5 before image replacement and then failed replay on Server 2.5.6. The three
new scalar regression cases also fail against the unchanged source.

Local tests pass: 2,454 non-integration tests, plus 49 final regression/corpus
cases after adding the damaged-history refusal. The local corpus validator
passes with one new replay fixture. Ruff and mypy pass.

CI on c209731093ef8aff51e099ccd635ea5d6248eb33 passes Python 3.10, 3.11 and
3.12, regression corpus, lint, package build/smoke, the developer portal and
public boundary checks. Connected integration passes:
https://github.com/durable-workflow/sdk-python/actions/runs/37582960588

Review checks the changed-code diagnostics before omitting a recorded command,
retains local activity preparation and leaves cancellation delivery ahead of
ordinary waiting. Shielded cleanup timers validate the original receipt and
authority without starting another timer. Existing damaged histories continue
to fail explicitly rather than being silently repaired.

Published 2.4.1
from merged source 7cae7f7395aded953d9f950442798c8e450cd4fc. Main qualification
and protected publication pass. Installed-package checks against immutable
Server 2.5.5 and 2.5.6 preserve the original pending timer, history, run identity
and 204800-byte external payload through signals and fresh workers. The waiting
run completes with total eighteen and one timer schedule/fire. Completed and
queued controls also complete correctly. The broader image exercise requires
PHP/Rust worker restarts and a guarded observer recovery.

Delivery details.
Issue #96 is closed after verification, and the merged GitHub branch is deleted.

@rmcdaniel
rmcdaniel marked this pull request as ready for review October 7, 2026 06:45
@rmcdaniel
rmcdaniel merged commit 7cae7f7 into main Oct 7, 2026
13 checks passed
@rmcdaniel
rmcdaniel deleted the fix/pending-operation-replay branch October 7, 2026 06:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants