Skip to content

Prevent timer callbacks after orchestration completion - #280

Merged
Bernd Verst (berndverst) merged 2 commits into
mainfrom
andystaples-prevent-timer-chunks-after-orchestration
Oct 2, 2026
Merged

Bernd Verst (berndverst) merged 2 commits into
mainfrom
andystaples-prevent-timer-chunks-after-orchestration

Conversation

@andystaples

@andystaples andystaples commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes #275.

Guard timerFired callbacks once the orchestration context is terminal. A later timer event can no longer schedule another long-timer chunk, dispatch an activity/sub-orchestration retry, or resume suspended orchestrator code after completion, failure, termination, or continue-as-new.

The guard is local to the timer callback, after task lookup and timer tracing. It does not break the history loop, change external-event handling, clear pending actions, or remove legitimate work scheduled before the terminal state. No Go coroutine-unwind/defer machinery is introduced; #274, #276, and #277 are intentionally out of scope.

Core and Azure Functions use chunked long timers. Azure Managed disables chunking because DTS supports native long timers; it benefits from the same terminal guard for retry dispatch and generator resumption, not a default chunk-continuation fix. All three Unreleased changelogs reflect this distinction. No versions or dependency minimums are changed; provider release coordination waits for the corrected core release.

Regression coverage

  • Completion, unhandled exceptions, output-serialization failure, termination, and continue-as-new, including a terminal transition in replayed history.
  • Trailing carryover events remain processed after the ignored timer callback.
  • Short/final timer callbacks cannot resume terminal orchestrators.
  • Activity and sub-orchestration retry callbacks with chunked and native timers; active retries still progress.
  • Ordinary multi-chunk progression, late cancellation, cancellation of a newly scheduled chunk, and preservation of pre-terminal timer/send-event actions.
  • Azure Functions worker response through both native and compatibility APIs.

Guard timer continuation at the executor callback boundary while preserving pre-terminal actions and trailing history processing. Cover terminal states, replay, native/chunked retries, cancellation, and Functions compatibility.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings September 29, 2026 17:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

The focused guard matches the requested lifecycle behavior and is supported by comprehensive regression coverage.

Review effort: Balanced
Findings: None

What changed in this PR

Prevents timer callbacks from producing work after an orchestration reaches a terminal state.

Changes:

  • Adds a terminal-state guard to timer processing.
  • Adds regression coverage for timers, retries, and both Functions APIs.
  • Documents behavior across all affected packages.
File Description
durabletask/​worker.py Skips terminal timer callbacks.
tests/​durabletask/​test_orchestration_executor.py Covers terminal timer and retry scenarios.
tests/​azure-functions-durable/​test_worker_compat.py Tests native and compatibility APIs.
CHANGELOG.md Documents the core fix.
durabletask-azuremanaged/​CHANGELOG.md Documents Azure Managed impact.
azure-functions-durable/​CHANGELOG.md Documents Functions provider impact.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@berndverst Bernd Verst (berndverst) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. The timer-local terminal guard prevents post-terminal work while preserving legitimate earlier actions and subsequent history processing. Active timer behavior is retained, and the provider changelogs accurately distinguish native and chunked timers. No unjustified breaking change or new Python-version requirement.

@berndverst
Bernd Verst (berndverst) merged commit 866cc78 into main Oct 2, 2026
24 checks passed
@berndverst
Bernd Verst (berndverst) deleted the andystaples-prevent-timer-chunks-after-orchestration branch October 2, 2026 01:04
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.

Prevent long timers from scheduling another chunk after orchestration completion

3 participants