Skip to content

Commit a5fe04d

Browse files
rekmarksclaude
andcommitted
refactor(kernel-browser-runtime): Simplify kernel worker initialization
The kernel worker initialization was using a convoluted pattern where every incoming message had to traverse a promise chain, even after the server was initialized. This refactoring updates receiveInternalConnections to accept either a direct handler function or a promise that resolves to a handler, implements a lazy cache pattern where subsequent messages use the cached handler directly with zero promise overhead, and simplifies kernel-worker.ts to pass a handler promise instead of wrapping every message in a promise chain. The synchronous listener setup is preserved to avoid missing early connections, while eliminating the performance overhead of promise chaining on every message after initialization. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent f975a28 commit a5fe04d

File tree

2 files changed

+27
-7
lines changed

2 files changed

+27
-7
lines changed

packages/kernel-browser-runtime/src/internal-comms/internal-connections.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ const connectToInternalProcess = async (
103103
};
104104

105105
type ReceiveConnectionsOptions = Omit<Options, 'label'> & {
106-
handleInternalMessage: HandleInternalMessage;
106+
handleInternalMessage: HandleInternalMessage | Promise<HandleInternalMessage>;
107107
};
108108

109109
/**
@@ -112,7 +112,9 @@ type ReceiveConnectionsOptions = Omit<Options, 'label'> & {
112112
* processes have attempted to connect.
113113
*
114114
* @param options - The options for the connection.
115-
* @param options.handleInternalMessage - The function to handle the internal message.
115+
* @param options.handleInternalMessage - The function to handle the internal message,
116+
* or a promise that resolves to such a function. If a promise is provided, messages will
117+
* be buffered until the handler is ready, then subsequent messages are handled directly.
116118
* @param options.logger - The logger instance.
117119
* @param options.controlChannelName - The name of the control channel. Must match
118120
* the name used by {@link connectToKernel} on the other end.
@@ -122,6 +124,22 @@ export const receiveInternalConnections = ({
122124
logger,
123125
controlChannelName = COMMS_CONTROL_CHANNEL_NAME,
124126
}: ReceiveConnectionsOptions): void => {
127+
// Support both direct handler and promise-based handler
128+
let handler: HandleInternalMessage | null = null;
129+
let handlerReady: Promise<HandleInternalMessage>;
130+
131+
if (typeof handleInternalMessage === 'function') {
132+
// Direct handler - use immediately
133+
handler = handleInternalMessage;
134+
handlerReady = Promise.resolve(handleInternalMessage);
135+
} else {
136+
// Promise-based handler - cache once resolved
137+
handlerReady = handleInternalMessage.then((resolvedHandler) => {
138+
handler = resolvedHandler;
139+
return resolvedHandler;
140+
});
141+
}
142+
125143
const seenChannels = new Set<string>();
126144
new BroadcastChannel(controlChannelName).onmessage = (event) => {
127145
if (!isCommsControlMessage(event.data)) {
@@ -148,7 +166,9 @@ export const receiveInternalConnections = ({
148166
`Received message from internal process "${channelName}": ${JSON.stringify(message)}`,
149167
);
150168

151-
const reply = await handleInternalMessage(message);
169+
// Use cached handler if available, otherwise await once
170+
const messageHandler = handler ?? (await handlerReady);
171+
const reply = await messageHandler(message);
152172
if (reply !== undefined) {
153173
await kernelRpcStream.write(reply);
154174
}

packages/kernel-browser-runtime/src/kernel-worker/kernel-worker.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,18 +54,18 @@ async function main(): Promise<void> {
5454
resetStorage,
5555
},
5656
);
57-
const serverP = kernelP.then((kernel) => {
58-
return new JsonRpcServer({
57+
const handlerP = kernelP.then((kernel) => {
58+
const server = new JsonRpcServer({
5959
middleware: [
6060
makeLoggingMiddleware(logger.subLogger('kernel-command')),
6161
makePanelMessageMiddleware(kernel, kernelDatabase),
6262
],
6363
});
64+
return async (request: JsonRpcCall) => server.handle(request);
6465
});
6566

6667
receiveInternalConnections({
67-
handleInternalMessage: async (request) =>
68-
serverP.then(async (rpcServer) => rpcServer.handle(request)),
68+
handleInternalMessage: handlerP,
6969
logger,
7070
});
7171

0 commit comments

Comments
 (0)