fix: catch errors in controller message handler
This commit is contained in:
parent
87394d690c
commit
1103fcd2fd
2 changed files with 63 additions and 1 deletions
|
|
@ -95,3 +95,56 @@ test("closes the websocket when an outbound send throws", async () => {
|
||||||
session.close();
|
session.close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("continues processing inbound messages after a volume command fails", async () => {
|
||||||
|
const outboundMessages: string[] = [];
|
||||||
|
const session = createControllerSession(
|
||||||
|
fromPartial({
|
||||||
|
send: (message: string) => {
|
||||||
|
outboundMessages.push(message);
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
session.onMessage(
|
||||||
|
createControllerMessage("volume.command", {
|
||||||
|
commandId: "command-1",
|
||||||
|
command: {
|
||||||
|
name: "filesystem.browse",
|
||||||
|
path: "/path/that/does/not/exist",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
session.onMessage(createControllerMessage("heartbeat.ping", { sentAt: 123 }));
|
||||||
|
|
||||||
|
await waitForExpect(() => {
|
||||||
|
const parsedMessages = outboundMessages.map((message) => parseAgentMessage(message));
|
||||||
|
const volumeResult = parsedMessages.find(
|
||||||
|
(message) => message?.success && message.data.type === "volume.commandResult",
|
||||||
|
);
|
||||||
|
const heartbeatPong = parsedMessages.find(
|
||||||
|
(message) => message?.success && message.data.type === "heartbeat.pong",
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(volumeResult?.success).toBe(true);
|
||||||
|
if (!volumeResult || !volumeResult.success || volumeResult.data.type !== "volume.commandResult") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(volumeResult.data.payload).toEqual({
|
||||||
|
commandId: "command-1",
|
||||||
|
status: "error",
|
||||||
|
error: "ENOENT: no such file or directory, scandir '/path/that/does/not/exist'",
|
||||||
|
});
|
||||||
|
expect(heartbeatPong?.success).toBe(true);
|
||||||
|
if (!heartbeatPong || !heartbeatPong.success || heartbeatPong.data.type !== "heartbeat.pong") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(heartbeatPong.data.payload).toEqual({ sentAt: 123 });
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,16 @@ export const createControllerSession = (ws: WebSocket): ControllerSession => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
yield* handleControllerCommand(commandContext, parsed.data);
|
const commandEffect: Effect.Effect<unknown, unknown, never> = handleControllerCommand(
|
||||||
|
commandContext,
|
||||||
|
parsed.data,
|
||||||
|
);
|
||||||
|
|
||||||
|
yield* commandEffect.pipe(
|
||||||
|
Effect.catchAll((error) =>
|
||||||
|
Effect.sync(() => logger.error(`Failed to handle controller message: ${toMessage(error)}`)),
|
||||||
|
),
|
||||||
|
);
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue