Skip to content

Keep overlapping actor await publications isolated - #29

Merged
MiguelsPizza merged 1 commit into
mainfrom
alex/await-publication-reservation
Aug 23, 2026
Merged

Keep overlapping actor await publications isolated#29
MiguelsPizza merged 1 commit into
mainfrom
alex/await-publication-reservation

Conversation

@MiguelsPizza

Copy link
Copy Markdown
Contributor

Why

This is a correctness follow-up to #24 and #20. The explicit await transform correctly restores the captured actor in __resumeAwait, but the result promise is fulfilled just before that injected call runs. In a realm containing separately bundled actors, another actor can publish in that microtask gap and replace the realm-shared continuation identity. The first actor then resumes without its own input lock.

That violates the actor-owned resumption model behind Cloudflare's Durable Object input gates. It surfaced in Rook as a delegated run nondeterministically failing at sql.exec(): no input lock available while broadcasting a milestone to its parent.

What changed

  • Reserve the gap from transformed-result publication through __resumeAwait.
  • Share the reservation through Symbol.for(...), matching the independently bundled runtime shape already handled by current actor identity.
  • Retry competing publications as separate tasks.
  • Clear abandoned reservations at checkpoint end so a manually consumed transform token cannot wedge the realm.
  • Add a real-browser regression that imports two gate module copies and proves the second actor cannot publish before the first resumes.

This stays in the runtime boundary. Rook needs no gate shim or vendored Agents workaround. #27 remains the separate owner of loopback routing.

Verification

  • pnpm test — 960 tests passed across unit, workerd, Node, and browser lanes.
  • pnpm typecheck — passed.
  • pnpm check:package — passed.
  • Rook's exact delegated-run browser regression — passed 10/10 with this build; published 0.3.5 reproduced the lost-lock failure.
  • Rook's forwarded Discord messenger regression — passed.

A patch changeset is included; Rook can consume the released version after merge.

A transformed await previously published its result before __resumeAwait restored the owning actor. In a realm with independently bundled actors, another publication could enter that microtask gap and replace the shared continuation identity, so the first actor resumed under the wrong input gate.\n\nReserve that publication gap across runtime copies, release it at __resumeAwait, and retain a checkpoint-end escape hatch for abandoned transformed results. The browser regression loads two gate module copies to preserve the production failure shape.
@MiguelsPizza
MiguelsPizza merged commit 059433a into main Aug 23, 2026
1 check passed
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.

1 participant