-
Notifications
You must be signed in to change notification settings - Fork 9
Description
Problem
watchSubOrchestration in InMemoryOrchestrationBackend (packages/durabletask-js/src/testing/in-memory-backend.ts:592) intends to wait indefinitely for a sub-orchestration to complete, as explicitly documented by the inline comment:
// No timeout - sub-orchestration will eventually complete, fail, or be terminated
However, no timeoutMs argument is actually 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.
Root Cause
waitForState(instanceId, predicate) defaults timeoutMs to 30000. The comment in watchSubOrchestration says "No timeout" but no timeout argument is passed:
this.waitForState(
subInstanceId,
(inst) => this.isTerminalStatus(inst.status),
// No timeout - sub-orchestration will eventually complete, fail, or be terminated
)The comments are just inline annotations — they don't affect the function call, which silently uses the 30000ms default.
Proposed Fix
- Modify
waitForStateto support no-timeout mode whentimeoutMsis0(skip creating the setTimeout timer) - Pass
0fromwatchSubOrchestrationto match the documented intent - Add unit tests verifying sub-orchestrations with timer delays and failure propagation
Impact
Severity: Medium — affects the in-memory testing backend, not production gRPC communication.
Scenarios affected: Any test using the in-memory backend where a sub-orchestration takes more than 30 real seconds to complete (e.g., sub-orchestrations using timers, retry backoff, or waiting for external events). The parent orchestration hangs indefinitely because the sub-orchestration completion event is silently lost.