Skip to content

fix: Sub-orchestration watcher uses unintended 30s default timeout in InMemoryOrchestrationBackend#156

Merged
YunchuWang merged 2 commits intomainfrom
copilot-finds/bug/fix-sub-orchestration-watcher-timeout
Apr 13, 2026
Merged

fix: Sub-orchestration watcher uses unintended 30s default timeout in InMemoryOrchestrationBackend#156
YunchuWang merged 2 commits intomainfrom
copilot-finds/bug/fix-sub-orchestration-watcher-timeout

Conversation

@YunchuWang
Copy link
Copy Markdown
Member

Summary

Fixes #149

Bug: watchSubOrchestration in InMemoryOrchestrationBackend intends to wait indefinitely for a sub-orchestration to complete (as documented by the inline comment "No timeout"), but no timeoutMs argument is passed to waitForState, so the default 30-second timeout applies. After 30 seconds, the timeout error is silently swallowed by the .catch(() => {}) handler, and the completion/failure event is never delivered to the parent orchestration.

Changes

  • packages/durabletask-js/src/testing/in-memory-backend.ts — Modified waitForState to support no-timeout mode when timeoutMs is 0 (skips creating the setTimeout timer); updated watchSubOrchestration to pass 0 to match the documented intent
  • packages/durabletask-js/test/in-memory-backend.spec.ts — Added tests verifying sub-orchestrations with timer delays and failure propagation work correctly without the 30s timeout

Testing

All tests pass. Lint clean.

… InMemoryOrchestrationBackend

The watchSubOrchestration method in InMemoryOrchestrationBackend intended to wait
indefinitely for sub-orchestrations to complete (as documented by the inline comment
'No timeout'), but actually used the default 30-second timeout from waitForState.
After 30 seconds, the watcher silently dropped the completion event via .catch(),
causing the parent orchestration to hang indefinitely.

Fix:
- Modified waitForState to support no-timeout mode when timeoutMs is 0
- Updated watchSubOrchestration to pass timeoutMs=0 matching the documented intent
- Added tests for sub-orchestrations with timer delays and failure propagation
- Added tests for waitForState zero-timeout behavior and cleanup on reset

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 10, 2026 16:32
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes an in-memory testing backend bug where sub-orchestration completion watching unintentionally timed out after 30 seconds (and silently swallowed the timeout), preventing the parent orchestration from receiving the child completion/failure event.

Changes:

  • Add “no-timeout” support to InMemoryOrchestrationBackend.waitForState when timeoutMs === 0 (skip setTimeout creation).
  • Update sub-orchestration watcher to pass 0 to waitForState to truly wait indefinitely.
  • Add unit tests covering sub-orchestration timer delays/failure propagation and waitForState(..., 0) behavior.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
packages/durabletask-js/src/testing/in-memory-backend.ts Implements no-timeout mode for state waiting and applies it to sub-orchestration watching.
packages/durabletask-js/test/in-memory-backend.spec.ts Adds regression/behavior tests around sub-orchestrations and zero-timeout waiting.

Comment on lines 595 to 599
this.waitForState(
subInstanceId,
(inst) => this.isTerminalStatus(inst.status),
// No timeout - sub-orchestration will eventually complete, fail, or be terminated
// If parent is terminated, we check that when delivering the event
0, // No timeout — sub-orchestration will eventually complete, fail, or be terminated
)
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

Now that waitForState(..., 0) can’t time out, the .catch comment below that mentions “Timeout” is misleading. Consider updating the comment to reflect the only expected cancellation path here (backend reset), or explicitly note any other errors you intend to swallow.

Copilot uses AI. Check for mistakes.
@YunchuWang YunchuWang merged commit e8ad92f into main Apr 13, 2026
28 checks passed
@YunchuWang YunchuWang deleted the copilot-finds/bug/fix-sub-orchestration-watcher-timeout branch April 13, 2026 22:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[copilot-finds] Bug: Sub-orchestration watcher in InMemoryOrchestrationBackend uses unintended 30s default timeout

3 participants