mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-08-31 16:21:50 +03:00
fix(webui): snapshot mutation replay frames
This commit is contained in:
@@ -109,10 +109,8 @@ interface PendingRequest<T> {
|
|||||||
timer: ReturnType<typeof setTimeout>;
|
timer: ReturnType<typeof setTimeout>;
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebUIRequestFrame = Extract<Outbound, { type: "webui_request" }>;
|
|
||||||
|
|
||||||
interface PendingWebUIRequest extends PendingRequest<unknown> {
|
interface PendingWebUIRequest extends PendingRequest<unknown> {
|
||||||
frame: WebUIRequestFrame;
|
serializedFrame: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class WebUIMutationError extends Error {
|
export class WebUIMutationError extends Error {
|
||||||
@@ -868,6 +866,13 @@ export class NanobotClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new Promise<T>((resolve, reject) => {
|
return new Promise<T>((resolve, reject) => {
|
||||||
|
let serializedFrame: string;
|
||||||
|
try {
|
||||||
|
serializedFrame = JSON.stringify(frame);
|
||||||
|
} catch {
|
||||||
|
reject(new WebUIMutationError(503, "Could not encode WebUI request"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
this.pendingWebUIRequests.delete(requestId);
|
this.pendingWebUIRequests.delete(requestId);
|
||||||
reject(
|
reject(
|
||||||
@@ -881,10 +886,10 @@ export class NanobotClient {
|
|||||||
resolve: (value) => resolve(value as T),
|
resolve: (value) => resolve(value as T),
|
||||||
reject,
|
reject,
|
||||||
timer,
|
timer,
|
||||||
frame,
|
serializedFrame,
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
socket.send(JSON.stringify(frame));
|
socket.send(serializedFrame);
|
||||||
} catch {
|
} catch {
|
||||||
clearTimeout(timer);
|
clearTimeout(timer);
|
||||||
this.pendingWebUIRequests.delete(requestId);
|
this.pendingWebUIRequests.delete(requestId);
|
||||||
@@ -1028,7 +1033,7 @@ export class NanobotClient {
|
|||||||
this.rawSend({ type: "attach", chat_id: chatId });
|
this.rawSend({ type: "attach", chat_id: chatId });
|
||||||
}
|
}
|
||||||
for (const pending of this.pendingWebUIRequests.values()) {
|
for (const pending of this.pendingWebUIRequests.values()) {
|
||||||
this.rawSend(pending.frame);
|
this.rawSendSerialized(pending.serializedFrame);
|
||||||
}
|
}
|
||||||
// Flush anything queued during reconnect.
|
// Flush anything queued during reconnect.
|
||||||
const queued = this.sendQueue.splice(0);
|
const queued = this.sendQueue.splice(0);
|
||||||
@@ -1476,4 +1481,13 @@ export class NanobotClient {
|
|||||||
this.sendQueue.push(frame);
|
this.sendQueue.push(frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private rawSendSerialized(serializedFrame: string): void {
|
||||||
|
if (!this.socket) return;
|
||||||
|
try {
|
||||||
|
this.socket.send(serializedFrame);
|
||||||
|
} catch {
|
||||||
|
// The pending request remains available for the next successful reconnect.
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -183,12 +183,12 @@ describe("NanobotClient", () => {
|
|||||||
const firstSocket = lastSocket();
|
const firstSocket = lastSocket();
|
||||||
firstSocket.fakeOpen();
|
firstSocket.fakeOpen();
|
||||||
|
|
||||||
const pending = client.requestMutation<{ ran: boolean }>(
|
const payload = { id: "daily-summary", options: { force: false } };
|
||||||
"automation.run",
|
const pending = client.requestMutation<{ ran: boolean }>("automation.run", payload);
|
||||||
{ id: "daily-summary" },
|
|
||||||
);
|
|
||||||
const frame = firstSocket.sent.at(-1) as string;
|
const frame = firstSocket.sent.at(-1) as string;
|
||||||
const requestId = JSON.parse(frame).request_id;
|
const requestId = JSON.parse(frame).request_id;
|
||||||
|
payload.id = "weekly-summary";
|
||||||
|
payload.options.force = true;
|
||||||
const settled = expect(pending).resolves.toEqual({ ran: true });
|
const settled = expect(pending).resolves.toEqual({ ran: true });
|
||||||
firstSocket.fakeCloseWithCode(1006);
|
firstSocket.fakeCloseWithCode(1006);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user