test(InProcessTestHost): external-event + durable-timer timeout coverage (relates to #713)#764
Merged
Merged
Conversation
…overage Adds InProcessTestHost.Tests coverage for WaitForExternalEvent, including the canonical Task.WhenAny timeout pattern that cancels the durable timer when the event wins. Documents that an orchestration does not complete while a durable timer is still outstanding. Relates to #713. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds new InProcessTestHost.Tests coverage for external event delivery (TaskOrchestrationContext.WaitForExternalEvent<T>), including the common “external event with durable-timer timeout” Task.WhenAny pattern described in #713, to document correct completion/cancellation behavior in the in-process test host.
Changes:
- Added a new test suite validating basic external-event delivery.
- Added timeout-pattern tests covering both “event wins” and “timer wins” branches.
- Included remarks in the test file that point to the durable-timer cancellation requirement documentation.
kaibocai
previously approved these changes
Jul 15, 2026
Use WaitForInstanceStartAsync instead of fixed delays, and cancel the losing external-event wait in the timeout branch to mirror the SDK's WaitForExternalEvent(name, timeout) helper. Relates to #713. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
halspang
approved these changes
Jul 15, 2026
kaibocai
approved these changes
Jul 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
InProcessTestHost.Testscoverage for external events (TaskOrchestrationContext.WaitForExternalEvent<T>), including the canonicalTask.WhenAny(eventTask, timerTask)"wait for an event with a timeout" pattern. This fills a gap in external-event test coverage and documents the correct durable-timer cancellation semantics.Relates to #713.
Background — #713 is expected behavior
#713 reports that an orchestration awaiting
Task.WhenAny(externalEventTask, timerTask)appears to "hang" after the external event is raised, while the durable timer is still pending.A verification-only investigation shows the external event is delivered and wins the
WhenAny. The orchestration does not complete because a durable timer that was created but never cancelled remains outstanding. This is standard Durable Task Framework behavior, already documented onTaskOrchestrationContext.CreateTimer:and on Microsoft Learn (durable-functions-timers): the framework doesn't change an orchestration's status to Completed until all outstanding tasks, including durable timer tasks, are either completed or canceled.
The issue's repro uses a 5-minute timer and never cancels it, so the instance stays
Runninguntil the timer would fire (~5 min) — which looks like a hang inside a short test. This is not a lost/dropped event and not an InProcessTestHost-specific defect: the worker forwards theCancellationTokenstraight intoDurableTask.Core(TaskOrchestrationContextWrapper.CreateTimer), the same path all backends use.What this PR adds
test/InProcessTestHost.Tests/ExternalEventTests.cswith three fast, deterministic tests:WaitForExternalEvent_IsDelivered— a plain external event is delivered to a waiting orchestration and its payload is returned (fills the missing plain external-event coverage).WaitForExternalEvent_WithTimeout_EventWins— the canonical pattern: a 5-minute timer underTask.WhenAny; when the event wins, the timer'sCancellationTokenSourceis cancelled so the orchestration completes promptly (well under the timer) with the event payload.WaitForExternalEvent_WithTimeout_TimerWins— same shape with a short 2 s timer and no event raised; the timer wins and the orchestration returns"timeout".Each test uses a 30 s completion
CancellationTokenSourcepurely as a safety guard; all complete in a few seconds.Notes
CreateTimercancellation/completion semantics are already documented on the public API, so this PR only adds tests (with a summary comment in the test file pointing at those docs). It does not change observable behavior.Validation
dotnet test test/InProcessTestHost.Tests/InProcessTestHost.Tests.csproj -c Debug -f net10.0→ 22 passed, 0 failed (3 new tests + 19 existing).