fix(discord): reconnect after missed identify · openclaw/openclaw@93e2d90
steipete
·
2026-05-02
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
@@ -28,6 +28,7 @@ Docs: https://docs.openclaw.ai
|
28 | 28 | |
29 | 29 | ### Fixes |
30 | 30 | |
| 31 | +- Discord/gateway: reconnect when the gateway socket closes while waiting for the shared IDENTIFY concurrency window, instead of silently skipping IDENTIFY and leaving the bot online but unresponsive. Fixes #74617. Thanks @zeeskdr-ai. |
31 | 32 | - Telegram/startup: use the existing `getMe` request guard for the gateway bot probe instead of a fixed 2.5-second budget, and honor higher `timeoutSeconds` configs for slow Telegram API paths. Fixes #75783. Thanks @tankotan. |
32 | 33 | - Infer/media: report missing image-understanding and audio-transcription provider configuration for `image describe`, `image describe-many`, and `audio transcribe` instead of blaming the input path when no provider is available. Fixes #73569 and supersedes #73593, #74288, and #74495. Thanks @bittoby, @tmimmanuel, @Linux2010, and @vyctorbrzezowski. |
33 | 34 | - Docs/health: clarify that session listing surfaces stored conversation rows rather than Discord/channel socket liveness, and point connectivity checks at channel status and health probes. Fixes #70420. Thanks @ashersoutherncities-art and @martingarramon. |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -127,6 +127,42 @@ describe("GatewayPlugin", () => {
|
127 | 127 | await vi.waitFor(() => expect(errorSpy).toHaveBeenCalledWith(error)); |
128 | 128 | }); |
129 | 129 | |
| 130 | +it("reconnects when the socket closes while waiting for identify concurrency", async () => { |
| 131 | +vi.useFakeTimers(); |
| 132 | +vi.setSystemTime(0); |
| 133 | +await sharedGatewayIdentifyLimiter.wait({ shardId: 0, maxConcurrency: 1 }); |
| 134 | +const gateway = new TestGatewayPlugin({ |
| 135 | +autoInteractions: false, |
| 136 | +url: "wss://gateway.example.test", |
| 137 | +}); |
| 138 | +const errorSpy = vi.fn(); |
| 139 | +gateway.emitter.on("error", errorSpy); |
| 140 | + |
| 141 | +gateway.connect(false); |
| 142 | +const socket = gateway.sockets[0]; |
| 143 | +socket?.emit("open"); |
| 144 | +socket?.emit( |
| 145 | +"message", |
| 146 | +JSON.stringify({ |
| 147 | +op: GatewayOpcodes.Hello, |
| 148 | +d: { heartbeat_interval: 45_000 }, |
| 149 | +s: null, |
| 150 | +}), |
| 151 | +); |
| 152 | +if (socket) { |
| 153 | +socket.readyState = 3; |
| 154 | +} |
| 155 | + |
| 156 | +await vi.advanceTimersByTimeAsync(5_000); |
| 157 | +expect(errorSpy).toHaveBeenCalledWith( |
| 158 | +new Error("Discord gateway socket closed before IDENTIFY could be sent"), |
| 159 | +); |
| 160 | +await vi.advanceTimersByTimeAsync(2_000); |
| 161 | + |
| 162 | +expect(gateway.connectCalls).toEqual([false, false]); |
| 163 | +expect(gateway.sockets).toHaveLength(2); |
| 164 | +}); |
| 165 | + |
130 | 166 | it("preserves MESSAGE_CREATE author payloads for inbound dispatch", async () => { |
131 | 167 | const gateway = new GatewayPlugin({ autoInteractions: false }); |
132 | 168 | const dispatchGatewayEvent = vi.fn(async (_event: string, _data: unknown) => {}); |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -248,7 +248,12 @@ export class GatewayPlugin extends Plugin {
|
248 | 248 | true, |
249 | 249 | ); |
250 | 250 | } else { |
251 | | -void this.identifyWithConcurrency(); |
| 251 | +void this.identifyWithConcurrency().catch((error: unknown) => { |
| 252 | +this.emitter.emit( |
| 253 | +"error", |
| 254 | +error instanceof Error ? error : new Error(String(error), { cause: error }), |
| 255 | +); |
| 256 | +}); |
252 | 257 | } |
253 | 258 | break; |
254 | 259 | case GatewayOpcodes.HeartbeatAck: |
@@ -325,7 +330,13 @@ export class GatewayPlugin extends Plugin {
|
325 | 330 | shardId: this.shardId, |
326 | 331 | maxConcurrency: this.gatewayInfo?.session_start_limit.max_concurrency, |
327 | 332 | }); |
328 | | -if (!this.ws || this.ws.readyState !== READY_STATE_OPEN) { |
| 333 | +const socket = this.ws; |
| 334 | +if (!socket || socket.readyState !== READY_STATE_OPEN) { |
| 335 | +const error = new Error("Discord gateway socket closed before IDENTIFY could be sent"); |
| 336 | +this.emitter.emit("error", error); |
| 337 | +if (socket) { |
| 338 | +this.scheduleReconnect(false); |
| 339 | +} |
329 | 340 | return; |
330 | 341 | } |
331 | 342 | this.identify(); |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。