Skip to content

Fix ExternalPusherImpl so it doesn't care about ordering.#6607

Merged
kentonv merged 2 commits into
mainfrom
kenton/fix-external-pusher
Apr 20, 2026
Merged

Fix ExternalPusherImpl so it doesn't care about ordering.#6607
kentonv merged 2 commits into
mainfrom
kenton/fix-external-pusher

Conversation

@kentonv

@kentonv kentonv commented Apr 19, 2026

Copy link
Copy Markdown
Member

Previously, ExternalPusherImpl assumed that the push RPC would always be received before the corresponding unwrap method was called during deserialization.

We seem to have cases in production where this assumption isn't holding.

It turns out, though, we don't have to make the assumption. We can actually deal with the push coming after the unwrap just fine, if we are clever.

Honestly, I had a feeling I'd burn myself trying to create tryGetLocalServerSync()...

@kentonv kentonv requested a review from npaun April 19, 2026 01:23
@kentonv kentonv requested review from a team as code owners April 19, 2026 01:23
@ask-bonk

ask-bonk Bot commented Apr 19, 2026

Copy link
Copy Markdown
Contributor

ProviderModelNotFoundError

github run

@ask-bonk

ask-bonk Bot commented Apr 19, 2026

Copy link
Copy Markdown
Contributor

@kentonv Bonk workflow failed. Check the logs for details.

View workflow run · To retry, trigger Bonk again.

@kentonv kentonv force-pushed the kenton/fix-external-pusher branch from 038de1e to fc8809d Compare April 19, 2026 15:07
@kentonv

kentonv commented Apr 19, 2026

Copy link
Copy Markdown
Member Author

/bonk retry review

@ask-bonk ask-bonk Bot 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.

  • [LOW] Stale ordering comment in worker-interface.capnp — the comment on line 596-597 still claims externals must be pushed before the JsValue, but this PR explicitly removes that requirement. See inline comment.
  • [LOW] Minor typo in pushAbortSignal comment: "the the" → "the".

This review was written by an AI assistant and may contain mistakes. Please verify any suggestions before applying.

@ask-bonk

ask-bonk Bot commented Apr 19, 2026

Copy link
Copy Markdown
Contributor

Stale comment in worker-interface.capnp: Lines 596-597 still say:

Note that externals must be pushed BEFORE the JsValue that uses them is sent, so that they can be unwrapped immediately when deserializing the value.

This is no longer accurate after this PR — the implementation now handles either ordering. Consider updating this comment.

Comment thread src/workerd/io/external-pusher.c++ Outdated
@ask-bonk

ask-bonk Bot commented Apr 19, 2026

Copy link
Copy Markdown
Contributor

Review posted on PR #6607. Here's a summary of my analysis:

Overall: This is a well-structured fix. The core change replaces tryGetLocalServerSync() (which required the push RPC to arrive before unwrap) with async getLocalServer() (which waits for the push if needed). The approach is sound.

Key observations:

  1. Stream unwrap (unwrapStreamImpl): Uses kj::newPromisedStream() to return a synchronous kj::Own<kj::AsyncInputStream> backed by a promise. The async resolution via getLocalServer() is correctly hidden behind the promised stream. No reference lifetime issues — unwrapped is used immediately after co_await with no intervening suspension points.

  2. AbortSignal unwrap (unwrapAbortSignalImpl): The deferred trigger pattern is clever — pushAbortSignal() returns a promise-for-capability as the trigger, and unwrapAbortSignalImpl() fulfills it later with the actual AbortTriggerRpcServer once it can allocate the PendingAbortReason synchronously. The inner block scoping correctly ensures unwrapped and cap don't outlive their valid use, and the co_await paf.promise at the end keeps the coroutine alive until the abort signal fires. No dangling reference issues.

  3. HACK removal in worker-rpc.c++: The extra event-loop turn that was inserted to ensure push-before-unwrap ordering is no longer needed since the implementation now handles either ordering. Clean removal.

Two minor findings posted:

  • Stale comment in worker-interface.capnp (lines 596-597) still says externals must be pushed before the JsValue — no longer accurate.
  • Typo "the the" in external-pusher.c++ line 211.

github run

kentonv added 2 commits April 19, 2026 10:22
Previously, `ExternalPusherImpl` _assumed_ that the `push` RPC would always be received before the corresponding `unwrap` method was called during deserialization.

We seem to have cases in production where this assumption isn't holding.

It turns out, though, we don't have to make the assumption. We can actually deal with the push coming after the unwrap just fine, if we are clever.

Honestly, I had a feeling I'd burn myself trying to create `tryGetLocalServerSync()`...
@kentonv kentonv force-pushed the kenton/fix-external-pusher branch from fc8809d to 577d2d4 Compare April 19, 2026 15:22
Comment thread src/workerd/io/external-pusher.c++
@kentonv kentonv merged commit 6b87702 into main Apr 20, 2026
30 checks passed
@kentonv kentonv deleted the kenton/fix-external-pusher branch April 20, 2026 17:50
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.

3 participants