Skip to content

Gate interrupt e2e's run-signal assertion under alwaysReplay - #774

Open
nstandif wants to merge 1 commit into
restatedev:mainfrom
nstandif:fix-interrupt-e2e-alwaysreplay
Open

Gate interrupt e2e's run-signal assertion under alwaysReplay#774
nstandif wants to merge 1 commit into
restatedev:mainfrom
nstandif:fix-interrupt-e2e-alwaysreplay

Conversation

@nstandif

Copy link
Copy Markdown
Contributor

Fixes #773.

Under alwaysReplay, delivering a sibling fiber's already-ready durable completion requires the attempt to suspend, but the SDK won't suspend while a run() is still pending — and that run() can only stop being pending via interrupt() (gated behind that same suspend) or its own fallback. Closed loop: the run signal never gets a chance to observe the abort in that mode, only its own fallback ever fires, regardless of the fallback's duration (measured at 0/200/5000/20000ms — same outcome, different speed).

The journaled interrupt-delivery path (this.wake throwing into the fiber, the actual SDK contract this test verifies) is unaffected — result passes 100% reliably in every mode and every variant tested. Only the auxiliary, non-journaled obs.worker side-channel is unobservable under alwaysReplay by construction.

Changes

packages/libs/restate-sdk-gen/e2e/interrupt.e2e.test.ts

  • Gate expect(obs.worker).toBe("aborted") to !alwaysReplay; keep the result assertion unconditional in both modes.
  • Clean up waitForAbort's abort listener and fallback timer so the promise settles exactly once instead of leaving both live after resolution — this masked the real issue before: a stale listener firing after the promise had already resolved via timeout was overwriting obs.worker back to "aborted".

Testing

Verified against current main (3/3 green) and against #771's node_endpoint.ts fix cherry-picked on top (3/3 green), so this doesn't depend on merge order between the two PRs.

Under alwaysReplay, delivering a sibling fiber's already-ready durable
completion requires the attempt to suspend, but the SDK won't suspend
while a run() is still pending — and that run() can only stop being
pending via interrupt() (gated behind that same suspend) or its own
fallback. Closed loop: the run signal never has a chance to observe
the abort in that mode, only its own fallback ever fires. The
journaled interrupt-delivery path (the actual SDK contract under
test) is unaffected and asserted unconditionally in both modes.

Also clean up waitForAbort's abort listener and fallback timer so the
promise settles exactly once, instead of leaving both live after
resolution.
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.

alwaysReplay: run()'s AbortSignal can't observe a sibling fiber's interrupt() within one attempt

1 participant