-
Notifications
You must be signed in to change notification settings - Fork 479
Add WorkerdDebugPort interface for dynamic RPC entrypoint access #5568
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
ffbdd7c to
df9b629
Compare
CodSpeed Performance ReportMerging #5568 will not alter performanceComparing Summary
Footnotes
|
df9b629 to
e207ace
Compare
|
The generated output of |
e207ace to
0d92e30
Compare
277dee0 to
9389f13
Compare
Introduces a new privileged debug port interface that enables dynamic
access to worker entrypoints at runtime.
Currently, service bindings between workerd processes must be configured
at startup in the config file. Changing binding targets requires a full
process restart. This is problematic for local development tools like
Miniflare, which need to dynamically re-target RPC connections at runtime.
Today, Miniflare works around this by running a Node.js TCP server that
sits between workerd processes and manually re-routes RPC traffic. This
adds significant complexity and overhead.
This commit implements the WorkerdDebugPort interface which exposes all
service entrypoints in a process through a privileged RPC interface.
External tools can now:
- Get direct access to any entrypoint with custom props at runtime
- Start events and invoke methods via JS RPC without HTTP overhead
- Dynamically switch between entrypoints without process restarts
This enables Miniflare to eliminate its TCP proxy layer and handle
dynamic RPC routing natively through workerd.
```
interface WorkerdDebugPort {
getEntrypoint(service, entrypoint, props) -> (worker)
getActor(service, entrypoint, actorId) -> (actor);
}
```
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <[email protected]>
9389f13 to
452a4c4
Compare
| return s.accept(conn); | ||
| } | ||
|
|
||
| public: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It appears the intent here is to make WorkerdBootstrapImpl public, but this line actually makes the whole rest of the class public, including things that aren't needed.
It seems to me that WrokerdBootstrapImpl should actually be moved out of HttpListener. Previously it was an implementation detail used only by HttpListener, but now some other code unrelated to HttpListener wants to reuse the same implementation. So it needs to live elsewhere. And EventDispatcherImpl should probably become a private nested class inside WorkerdBootstrapImpl...
| tasks(*this) {} | ||
|
|
||
| kj::Promise<void> run() { | ||
| for (;;) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This for loop and the confusingly-named acceptLoop() method (confusing because it doesn't encapsulate the loop) could be replaced with just using capnp::TwoPartyServer::listen(), which implements the accept loop for you.
| if (workerService != nullptr) { | ||
| // This is a WorkerService, use getEntrypoint which supports both entrypoints and props | ||
| kj::Maybe<kj::StringPtr> maybeEntrypoint; | ||
| if (entrypointName.size() > 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use params.hasEntrypoint() rather than checking for a zero-length string. (Here and below.)
| auto service = serviceEntry->service(); | ||
|
|
||
| // Convert props from Frankenvalue | ||
| Frankenvalue props = Frankenvalue::fromCapnp(propsReader); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably should check params.hasProps() and skip calling fromCapnp() on default props. (A default-initialized Frankenvalue is all you want.)
| actorIdData.size() == SHA256_DIGEST_LENGTH, "Invalid actor ID size", actorIdData.size()); | ||
|
|
||
| // Create an ActorId from the provided bytes | ||
| kj::Own<ActorIdFactory::ActorId> actorId = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This only supports Durable Objects. If the actor namespace is emphemeral (aka colo-local) then the ID is a plain string, not an ActorId.
Introduces a new privileged debug port interface that enables dynamic access to worker entrypoints at runtime.
Currently, service bindings between workerd processes must be configured at startup in the config file. Changing binding targets requires a full process restart. This is problematic for local development tools like Miniflare, which need to dynamically re-target RPC connections at runtime.
Today, Miniflare works around this by running a Node.js TCP server that sits between workerd processes and manually re-routes RPC traffic. This adds significant complexity and overhead.
This commit implements the WorkerdDebugPort interface which exposes all service entrypoints in a process through a privileged RPC interface. External tools can now:
This enables Miniflare to eliminate its TCP proxy layer and handle dynamic RPC routing natively through workerd.
🤖 Generated with Claude Code