fix(webui): make mutations reconnect-safe
This commit is contained in:
@@ -172,6 +172,64 @@ describe("NanobotClient", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("retries in-flight WebUI mutations with the same request id after reconnect", async () => {
|
||||
const client = new NanobotClient({
|
||||
url: "ws://test",
|
||||
reconnect: true,
|
||||
maxBackoffMs: 10,
|
||||
socketFactory: (url) => new FakeSocket(url) as unknown as WebSocket,
|
||||
});
|
||||
client.connect();
|
||||
const firstSocket = lastSocket();
|
||||
firstSocket.fakeOpen();
|
||||
|
||||
const pending = client.requestMutation<{ ran: boolean }>(
|
||||
"automation.run",
|
||||
{ id: "daily-summary" },
|
||||
);
|
||||
const frame = firstSocket.sent.at(-1) as string;
|
||||
const requestId = JSON.parse(frame).request_id;
|
||||
const settled = expect(pending).resolves.toEqual({ ran: true });
|
||||
firstSocket.fakeCloseWithCode(1006);
|
||||
|
||||
await vi.advanceTimersByTimeAsync(20);
|
||||
const retrySocket = lastSocket();
|
||||
retrySocket.fakeOpen();
|
||||
expect(retrySocket.sent).toEqual([frame]);
|
||||
retrySocket.fakeMessage({
|
||||
event: "webui_response",
|
||||
request_id: requestId,
|
||||
ok: true,
|
||||
result: { ran: true },
|
||||
});
|
||||
|
||||
await settled;
|
||||
});
|
||||
|
||||
it("does not retry a WebUI mutation after its timeout expires", async () => {
|
||||
const client = new NanobotClient({
|
||||
url: "ws://test",
|
||||
reconnect: true,
|
||||
maxBackoffMs: 1_000,
|
||||
socketFactory: (url) => new FakeSocket(url) as unknown as WebSocket,
|
||||
});
|
||||
client.connect();
|
||||
const firstSocket = lastSocket();
|
||||
firstSocket.fakeOpen();
|
||||
|
||||
const pending = expect(
|
||||
client.requestMutation("skill.install", { skill: "docs" }, 25),
|
||||
).rejects.toMatchObject({ status: 504 });
|
||||
firstSocket.fakeCloseWithCode(1006);
|
||||
await vi.advanceTimersByTimeAsync(25);
|
||||
await pending;
|
||||
|
||||
await vi.advanceTimersByTimeAsync(1_000);
|
||||
const retrySocket = lastSocket();
|
||||
retrySocket.fakeOpen();
|
||||
expect(retrySocket.sent).toEqual([]);
|
||||
});
|
||||
|
||||
it("does not queue WebUI mutations before the authenticated socket opens", async () => {
|
||||
const client = new NanobotClient({
|
||||
url: "ws://test",
|
||||
|
||||
Reference in New Issue
Block a user