Skip to content

Fix continueAsNew dropping fire-and-forget actions (sendEvent, signal…#136

Merged
YunchuWang merged 1 commit intomainfrom
copilot-finds/bug/continue-as-new-drops-fire-and-forget-actions
Mar 5, 2026
Merged

Fix continueAsNew dropping fire-and-forget actions (sendEvent, signal…#136
YunchuWang merged 1 commit intomainfrom
copilot-finds/bug/continue-as-new-drops-fire-and-forget-actions

Conversation

@YunchuWang
Copy link
Member

@YunchuWang YunchuWang commented Mar 5, 2026

Fix #124
Problem
When an orchestration calls sendEvent() or signalEntity() before continueAsNew(), those fire-and-forget actions are silently dropped.

File: packages/durabletask-js/src/worker/runtime-orchestration-context.ts

In getActions() (line 243), when the completion status is CONTINUED_AS_NEW, only the single continue-as-new completion action is returned, dropping all other pending actions (including fire-and-forget actions like sendEvent). This is inconsistent with setComplete() (line 195) and setFailed() (line 217), which both preserve pending fire-and-forget actions.

Both setComplete and setFailed have explicit comments:

Note: Do NOT clear pending actions here - fire-and-forget actions like sendEvent must be preserved and returned alongside the complete action

Root Cause
setContinuedAsNew() stores only flags (_newInput, _saveEvents) without adding the completion action to _pendingActions. Then getActions() creates a fresh completion action and returns [action] as the sole item, discarding everything in _pendingActions.

Fix Available
Branch: copilot-finds/bug/continue-as-new-drops-fire-and-forget-actions

The fix modifies getActions() to include all pending actions alongside the continue-as-new completion action. A new unit test verifies that sendEvent actions scheduled before continueAsNew are preserved and delivered.

Summary

What changed?

Why is this change needed?

Issues / work items

  • Resolves #
  • Related #

Project checklist

  • Release notes are not required for the next release
    • Otherwise: Notes added to CHANGELOG.md
  • Backport is not required
    • Otherwise: Backport tracked by issue/PR #issue_or_pr
  • All required tests have been added/updated (unit tests, E2E tests)
  • Breaking change?
    • If yes:
      • Impact:
      • Migration guidance:

AI-assisted code disclosure (required)

Was an AI tool used? (select one)

  • No
  • Yes, AI helped write parts of this PR (e.g., GitHub Copilot)
  • Yes, an AI agent generated most of this PR

If AI was used:

  • Tool(s):
  • AI-assisted areas/files:
  • What you changed after AI output:

AI verification (required if AI was used):

  • I understand the code and can explain it
  • I verified referenced APIs/types exist and are correct
  • I reviewed edge cases/failure paths (timeouts, retries, cancellation, exceptions)
  • I reviewed concurrency/async behavior
  • I checked for unintended breaking or behavior changes

Testing

Automated tests

  • Result: Passed / Failed (link logs if failed)

Manual validation (only if runtime/behavior changed)

  • Environment (OS, Node.js version, components):
  • Steps + observed results:
    1.
    2.
    3.
  • Evidence (optional):

Notes for reviewers

  • N/A

…Entity)

When an orchestration called sendEvent() or signalEntity() before
continueAsNew(), those fire-and-forget actions were silently dropped
because getActions() returned only the continue-as-new completion
action, ignoring all other pending actions.

This is inconsistent with setComplete() and setFailed(), which both
preserve pending fire-and-forget actions alongside the completion
action. The fix makes getActions() include all pending actions when
continuing-as-new, matching the behavior of the other completion paths.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 5, 2026 20:54
Copy link

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

Fixes a core orchestration runtime behavior where continueAsNew() previously caused pending fire-and-forget actions (e.g., sendEvent, signalEntity) to be dropped by getActions(). This aligns the continue-as-new completion path with the existing setComplete() / setFailed() behavior in the Durable Task JS SDK.

Changes:

  • Update RuntimeOrchestrationContext.getActions() to return all pending actions plus the continue-as-new completion action.
  • Add an in-memory backend regression test validating that sendEvent() is preserved across continueAsNew().

Reviewed changes

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

File Description
packages/durabletask-js/src/worker/runtime-orchestration-context.ts Ensure continue-as-new returns pending actions (fire-and-forget) alongside the completion action.
packages/durabletask-js/test/in-memory-backend.spec.ts Add regression coverage verifying sendEvent is not dropped when continuing-as-new.

@YunchuWang YunchuWang merged commit c2e439c into main Mar 5, 2026
32 checks passed
@YunchuWang YunchuWang deleted the copilot-finds/bug/continue-as-new-drops-fire-and-forget-actions branch March 5, 2026 21:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

sample-verification-added PR has been verified with a sample application

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[copilot-finds] Bug: continueAsNew drops fire-and-forget actions (sendEvent, signalEntity)

3 participants