fix(scripts): fail RPC RTT on websocket pre-open close · openclaw/openclaw@de17d5b
vincentkoc
·
2026-06-19
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
@@ -671,19 +671,31 @@ export function createGatewayClient({ WebSocket, openTimeoutMs = 8_000, url }) {
|
671 | 671 | clearTimeout(timer); |
672 | 672 | ws.off?.("open", onOpen); |
673 | 673 | ws.off?.("error", onError); |
| 674 | +ws.off?.("close", onClose); |
674 | 675 | callback(); |
675 | 676 | }; |
676 | 677 | const onOpen = () => settle(resolve); |
677 | 678 | const onError = (error) => |
678 | 679 | settle(() => reject(error instanceof Error ? error : new Error(String(error)))); |
| 680 | +const onClose = (code, reason) => |
| 681 | +settle(() => { |
| 682 | +const text = toText(reason); |
| 683 | +const suffix = text.length > 0 ? `: ${text}` : ""; |
| 684 | +reject(new Error(`closed before open (${code})${suffix}`)); |
| 685 | +}); |
679 | 686 | const timer = setTimeout(() => { |
680 | 687 | settle(() => { |
681 | | -ws.close(); |
| 688 | +if (typeof ws.terminate === "function") { |
| 689 | +ws.terminate(); |
| 690 | +} else { |
| 691 | +ws.close(); |
| 692 | +} |
682 | 693 | reject(new Error("gateway websocket open timeout")); |
683 | 694 | }); |
684 | 695 | }, openTimeoutMs); |
685 | 696 | ws.once("open", onOpen); |
686 | 697 | ws.once("error", onError); |
| 698 | +ws.once("close", onClose); |
687 | 699 | }); |
688 | 700 | const request = async (method, params, timeoutMs = 10_000) => |
689 | 701 | await new Promise((resolve, reject) => { |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -22,6 +22,7 @@ class FakeWebSocket extends EventEmitter {
|
22 | 22 | closed = false; |
23 | 23 | readyState = 0; |
24 | 24 | sent: string[] = []; |
| 25 | +terminated = false; |
25 | 26 | |
26 | 27 | constructor( |
27 | 28 | readonly url: string, |
@@ -41,6 +42,11 @@ class FakeWebSocket extends EventEmitter {
|
41 | 42 | this.readyState = 3; |
42 | 43 | this.emit("close", 1000, "closed"); |
43 | 44 | } |
| 45 | + |
| 46 | +terminate(): void { |
| 47 | +this.terminated = true; |
| 48 | +this.close(); |
| 49 | +} |
44 | 50 | } |
45 | 51 | |
46 | 52 | function jsonResponse(body: unknown, init: ResponseInit = {}): Response { |
@@ -58,6 +64,22 @@ describe("scripts/measure-rpc-rtt.mjs", () => {
|
58 | 64 | |
59 | 65 | await expect(client.waitOpen()).rejects.toThrow("gateway websocket open timeout"); |
60 | 66 | expect(FakeWebSocket.instances[0]?.closed).toBe(true); |
| 67 | +expect(FakeWebSocket.instances[0]?.terminated).toBe(true); |
| 68 | +}); |
| 69 | + |
| 70 | +it("rejects websocket closes before opening", async () => { |
| 71 | +FakeWebSocket.instances = []; |
| 72 | +const client = createGatewayClient({ |
| 73 | +WebSocket: FakeWebSocket, |
| 74 | +openTimeoutMs: 10_000, |
| 75 | +url: "ws://127.0.0.1:12345", |
| 76 | +}); |
| 77 | + |
| 78 | +const opened = client.waitOpen(); |
| 79 | +FakeWebSocket.instances[0]?.emit("close", 1006, Buffer.from("bye")); |
| 80 | + |
| 81 | +await expect(opened).rejects.toThrow("closed before open (1006): bye"); |
| 82 | +expect(FakeWebSocket.instances[0]?.closed).toBe(false); |
61 | 83 | }); |
62 | 84 | |
63 | 85 | it("rejects pending websocket requests when cleanup closes the client", async () => { |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。