fix: serialize rpc requests, no eager rewrites

This commit is contained in:
Cristina Poncela Cubeiro
2026-06-22 16:00:35 +02:00
parent d991055562
commit cc12750e8e
2 changed files with 40 additions and 21 deletions
+20 -11
View File
@@ -11,7 +11,6 @@ import {
type OrchestratorResponse, type OrchestratorResponse,
parseRequestLine, parseRequestLine,
type RpcBridgeResponse, type RpcBridgeResponse,
type RpcClientMessage,
type RpcReadyResponse, type RpcReadyResponse,
type RpcRequest, type RpcRequest,
type RpcStreamRequest, type RpcStreamRequest,
@@ -38,7 +37,7 @@ export interface IpcRequestHandler {
onUiRequest: (request: RpcExtensionUIRequest) => void, onUiRequest: (request: RpcExtensionUIRequest) => void,
): ):
| { | {
handleRequest(request: RpcClientMessage): Promise<void>; handleRequest(request: RpcRequest["command"] | { type: "extension_ui_response" }): Promise<void>;
close(): void; close(): void;
} }
| undefined; | undefined;
@@ -94,6 +93,7 @@ export async function startIpcServer(handler: IpcRequestHandler): Promise<Server
} }
socket.write(encodeMessage(response)); socket.write(encodeMessage(response));
let rpcRequestQueue = Promise.resolve();
socket.on("data", (rpcChunk: Buffer | string) => { socket.on("data", (rpcChunk: Buffer | string) => {
buffer += rpcChunk.toString(); buffer += rpcChunk.toString();
for (;;) { for (;;) {
@@ -106,20 +106,29 @@ export async function startIpcServer(handler: IpcRequestHandler): Promise<Server
if (!rpcLine) { if (!rpcLine) {
continue; continue;
} }
void (async () => { rpcRequestQueue = rpcRequestQueue
try { .then(async () => {
const rpcRequest = JSON.parse(rpcLine) as RpcClientMessage; try {
await rpcStream.handleRequest(rpcRequest); await rpcStream.handleRequest(JSON.parse(rpcLine));
} catch (rpcError) { } catch (rpcError: unknown) {
socket.write(
encodeMessage({
type: "error",
ok: false,
error: rpcError instanceof Error ? rpcError.message : String(rpcError),
}),
);
}
})
.catch((rpcError: Error) => {
socket.write( socket.write(
encodeMessage({ encodeMessage({
type: "error", type: "error",
ok: false, ok: false,
error: rpcError instanceof Error ? rpcError.message : String(rpcError), error: rpcError.message,
}), }),
); );
} });
})();
} }
}); });
socket.once("close", () => rpcStream.close()); socket.once("close", () => rpcStream.close());
@@ -128,7 +137,7 @@ export async function startIpcServer(handler: IpcRequestHandler): Promise<Server
const response = await handler(request); const response = await handler(request);
socket.end(encodeMessage(response)); socket.end(encodeMessage(response));
} catch (error) { } catch (error: unknown) {
const response: ErrorResponse = { const response: ErrorResponse = {
type: "error", type: "error",
ok: false, ok: false,
+20 -10
View File
@@ -9,21 +9,31 @@ import { supervisor } from "./supervisor.ts";
export async function serve(): Promise<void> { export async function serve(): Promise<void> {
const socketPath = getSocketPath(); const socketPath = getSocketPath();
mkdirSync(dirname(socketPath), { recursive: true }); mkdirSync(dirname(socketPath), { recursive: true });
await supervisor.recoverAfterRestart();
if (isRadiusEnabled()) {
const machine = await radiusPresence.start();
console.log(`radius integration enabled: ${socketPath} -> ${getRadiusOrchestratorBaseUrl()}`);
if (machine) {
console.log(`radius machine id: ${machine.id}`);
}
} else {
console.log("radius integration disabled: login radius in ~/.pi/agent/auth.json or set PI_RADIUS_API_KEY");
}
const server = await startIpcServer( const server = await startIpcServer(
Object.assign(handleIpcRequest, { Object.assign(handleIpcRequest, {
openRpcStream, openRpcStream,
}), }),
); );
try {
await supervisor.recoverAfterRestart();
if (isRadiusEnabled()) {
const machine = await radiusPresence.start();
console.log(`radius integration enabled: ${socketPath} -> ${getRadiusOrchestratorBaseUrl()}`);
if (machine) {
console.log(`radius machine id: ${machine.id}`);
}
} else {
console.log("radius integration disabled: login radius in ~/.pi/agent/auth.json or set PI_RADIUS_API_KEY");
}
} catch (error) {
server.close();
if (existsSync(socketPath)) {
unlinkSync(socketPath);
}
throw error;
}
console.log(`orchestrator listening on ${socketPath}`); console.log(`orchestrator listening on ${socketPath}`);
let shutdownPromise: Promise<void> | undefined; let shutdownPromise: Promise<void> | undefined;