fix: parse discord gateway timeouts strictly · openclaw/openclaw@5e33d7d
steipete
·
2026-05-29
·
via Recent Commits to openclaw:main
File tree
extensions/discord/src/monitor
| Original file line number | Diff line number | Diff line change |
|---|
|
1 | 1 | import { describe, expect, it, vi } from "vitest"; |
2 | | -import { fetchDiscordGatewayInfo, resolveGatewayInfoWithFallback } from "./gateway-metadata.js"; |
| 2 | +import { |
| 3 | +fetchDiscordGatewayInfo, |
| 4 | +resolveDiscordGatewayInfoTimeoutMs, |
| 5 | +resolveGatewayInfoWithFallback, |
| 6 | +} from "./gateway-metadata.js"; |
3 | 7 | |
4 | 8 | describe("Discord gateway metadata", () => { |
| 9 | +it("resolves gateway info timeouts from strict integer config and env values", () => { |
| 10 | +expect(resolveDiscordGatewayInfoTimeoutMs({ configuredTimeoutMs: 45_000 })).toBe(45_000); |
| 11 | +expect( |
| 12 | +resolveDiscordGatewayInfoTimeoutMs({ |
| 13 | +env: { OPENCLAW_DISCORD_GATEWAY_INFO_TIMEOUT_MS: "90000" }, |
| 14 | +}), |
| 15 | +).toBe(90_000); |
| 16 | +expect(resolveDiscordGatewayInfoTimeoutMs({ configuredTimeoutMs: 150_000 })).toBe(120_000); |
| 17 | +expect( |
| 18 | +resolveDiscordGatewayInfoTimeoutMs({ |
| 19 | +configuredTimeoutMs: 1.5, |
| 20 | +env: { OPENCLAW_DISCORD_GATEWAY_INFO_TIMEOUT_MS: "0x1000" }, |
| 21 | +}), |
| 22 | +).toBe(30_000); |
| 23 | +expect( |
| 24 | +resolveDiscordGatewayInfoTimeoutMs({ |
| 25 | +env: { OPENCLAW_DISCORD_GATEWAY_INFO_TIMEOUT_MS: "1e3" }, |
| 26 | +}), |
| 27 | +).toBe(30_000); |
| 28 | +}); |
| 29 | + |
5 | 30 | it("falls back on Cloudflare HTML rate limits without logging raw HTML", async () => { |
6 | 31 | const error = await fetchDiscordGatewayInfo({ |
7 | 32 | token: "test", |
|
| Original file line number | Diff line number | Diff line change |
|---|
|
1 | 1 | import type { APIGatewayBotInfo } from "discord-api-types/v10"; |
2 | 2 | import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime"; |
| 3 | +import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime"; |
3 | 4 | import { captureHttpExchange } from "openclaw/plugin-sdk/proxy-capture"; |
4 | 5 | import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env"; |
5 | 6 | import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime"; |
@@ -64,12 +65,11 @@ async function materializeGuardedResponse(response: Response): Promise<Response>
|
64 | 65 | } |
65 | 66 | |
66 | 67 | function normalizeGatewayInfoTimeoutMs(value: unknown): number | undefined { |
67 | | -const numeric = |
68 | | -typeof value === "number" ? value : typeof value === "string" ? Number(value) : Number.NaN; |
69 | | -if (!Number.isFinite(numeric) || numeric <= 0) { |
| 68 | +const numeric = parseStrictPositiveInteger(value); |
| 69 | +if (numeric === undefined) { |
70 | 70 | return undefined; |
71 | 71 | } |
72 | | -return Math.min(Math.floor(numeric), MAX_DISCORD_GATEWAY_INFO_TIMEOUT_MS); |
| 72 | +return Math.min(numeric, MAX_DISCORD_GATEWAY_INFO_TIMEOUT_MS); |
73 | 73 | } |
74 | 74 | |
75 | 75 | export function resolveDiscordGatewayInfoTimeoutMs(params?: { |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -233,6 +233,20 @@ describe("runDiscordGatewayLifecycle", () => {
|
233 | 233 | expect(resolveDiscordGatewayRuntimeReadyTimeoutMs({ env: {} })).toBe(30_000); |
234 | 234 | }); |
235 | 235 | |
| 236 | +it("ignores non-integer gateway READY timeout values", () => { |
| 237 | +expect( |
| 238 | +resolveDiscordGatewayReadyTimeoutMs({ |
| 239 | +configuredTimeoutMs: 1.5, |
| 240 | +env: { OPENCLAW_DISCORD_READY_TIMEOUT_MS: "0x1000" }, |
| 241 | +}), |
| 242 | +).toBe(15_000); |
| 243 | +expect( |
| 244 | +resolveDiscordGatewayRuntimeReadyTimeoutMs({ |
| 245 | +env: { OPENCLAW_DISCORD_RUNTIME_READY_TIMEOUT_MS: "1e3" }, |
| 246 | +}), |
| 247 | +).toBe(30_000); |
| 248 | +}); |
| 249 | + |
236 | 250 | it("cleans up thread bindings when gateway wait fails before READY", async () => { |
237 | 251 | waitForDiscordGatewayStopMock.mockRejectedValueOnce(new Error("startup failed")); |
238 | 252 | const { lifecycleParams, threadStop, gatewaySupervisor } = createLifecycleHarness(); |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -2,6 +2,7 @@ import {
|
2 | 2 | createConnectedChannelStatusPatch, |
3 | 3 | createTransportActivityStatusPatch, |
4 | 4 | } from "openclaw/plugin-sdk/gateway-runtime"; |
| 5 | +import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime"; |
5 | 6 | import { danger } from "openclaw/plugin-sdk/runtime-env"; |
6 | 7 | import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env"; |
7 | 8 | import { attachDiscordGatewayLogging } from "../gateway-logging.js"; |
@@ -33,12 +34,11 @@ const DISCORD_GATEWAY_TRANSPORT_ACTIVITY_STATUS_MIN_INTERVAL_MS = 30_000;
|
33 | 34 | type GatewayReadyWaitResult = "ready" | "stopped" | "timeout"; |
34 | 35 | |
35 | 36 | function normalizeGatewayReadyTimeoutMs(value: unknown): number | undefined { |
36 | | -const numeric = |
37 | | -typeof value === "number" ? value : typeof value === "string" ? Number(value) : Number.NaN; |
38 | | -if (!Number.isFinite(numeric) || numeric <= 0) { |
| 37 | +const numeric = parseStrictPositiveInteger(value); |
| 38 | +if (numeric === undefined) { |
39 | 39 | return undefined; |
40 | 40 | } |
41 | | -return Math.min(Math.floor(numeric), MAX_DISCORD_GATEWAY_READY_TIMEOUT_MS); |
| 41 | +return Math.min(numeric, MAX_DISCORD_GATEWAY_READY_TIMEOUT_MS); |
42 | 42 | } |
43 | 43 | |
44 | 44 | export function resolveDiscordGatewayReadyTimeoutMs(params?: { |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。