Skip to content

fix: remove stale waiter in waitForState timeout handler#330

Open
YunchuWang wants to merge 1 commit into
mainfrom
copilot-finds/bug/fix-waitforstate-timeout-cleanup
Open

fix: remove stale waiter in waitForState timeout handler#330
YunchuWang wants to merge 1 commit into
mainfrom
copilot-finds/bug/fix-waitforstate-timeout-cleanup

Conversation

@YunchuWang

Copy link
Copy Markdown
Member

Fixes #201.

The waitForState timeout handler failed to remove the stale waiter due to a reference mismatch, leaking waiters. This fixes the cleanup logic.


Opens the existing fix branch copilot-finds/bug/fix-waitforstate-timeout-cleanup as a PR (automated triage of active [copilot-finds] issues that had a ready fix branch but no open PR).

The timeout handler in InMemoryOrchestrationBackend.waitForState() used
findIndex with `w.resolve === resolve` to locate and remove the timed-out
waiter. However, the waiter's resolve property is a wrapper function that
calls clearTimeout before delegating to the original resolve, so the
identity check always failed and the stale waiter was never removed.

Fix:
- Move waiter declaration before timer so the timeout callback can use
  indexOf(waiter) for correct object-identity lookup.
- Track waitForState timers in pendingTimers so reset() cleans them up.
- Remove timer from pendingTimers on resolve, reject, and timeout.
- Delete the stateWaiters map entry when the last waiter is removed.

Fixes #201

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 23, 2026 16:39

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.

Pull request overview

Fixes a leak in the in-memory testing backend where waitForState() timeout handlers failed to remove stale waiters due to an identity/reference mismatch, causing stateWaiters to grow over time and timers to remain untracked across reset().

Changes:

  • Fix waiter cleanup on timeout by removing the exact waiter object (indexOf(waiter)) rather than comparing function references.
  • Track waitForState() timeout timers in pendingTimers, and remove them on resolve/reject/timeout so reset() can reliably clear them.
  • Add regression tests to ensure timed-out waiters are removed (both single-waiter and multi-waiter scenarios).

Reviewed changes

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

File Description
packages/durabletask-js/src/testing/in-memory-backend.ts Fixes waitForState() timeout cleanup and ensures timeout timers are tracked/removed via pendingTimers.
packages/durabletask-js/test/in-memory-backend.spec.ts Adds regression tests verifying stale waiter cleanup after timeouts (single and multiple waiters).

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.

[copilot-finds] Bug: waitForState timeout handler fails to remove stale waiter due to reference mismatch

2 participants