Skip to content

fix(qq): route long Send() through HTTP to dodge 15s WS timeout (#1474)#1480

Open
chenhg5 wants to merge 1 commit into
mainfrom
agent/cc-connect/dev-claudecode/t-20260701-y915u1-1474-qq-http-fallback
Open

fix(qq): route long Send() through HTTP to dodge 15s WS timeout (#1474)#1480
chenhg5 wants to merge 1 commit into
mainfrom
agent/cc-connect/dev-claudecode/t-20260701-y915u1-1474-qq-http-fallback

Conversation

@chenhg5

@chenhg5 chenhg5 commented Jul 1, 2026

Copy link
Copy Markdown
Owner

Fixes #1474

问题

Long replies (~2.5KB+) always timed out on QQ WebSocket send. Root cause: callAPI shares the WS connection readLoop with inbound events, so a long outbound reply queues behind inbound traffic and trips the hardcoded 15s timeout — leaving the bot silent in group chats for long-form agent output.

改动

New send_via_http config knob (default "auto") on the QQ OneBot platform:

value behavior
auto WS for ≤512 byte messages, HTTP for longer ones. Falls back to WS when http_url is unset.
always Always HTTP (requires http_url); falls back to WS when absent.
never Always WebSocket, even for long messages.

Invalid values fall back to "auto" with a WARN log. SendFile() and SendImage() are unaffected (separate code paths). HTTP path uses existing callHTTPAPI (120s timeout, dedicated connection).

触发条件 / trade-off

Reporter (#1474) proposed a 512-byte threshold — fixes the immediate symptom with zero config churn. Adding send_via_http lets users override either direction:

  • "always" — paranoid users who want every send off the shared WS path
  • "never" — users who trust WS and don't want HTTP exposure
  • Why fall back to WS when http_url is empty? Failing every send because the user didn't configure HTTP would be a regression. Better to deliver via the available path. Matches existing SendFile() behavior.

测试

新增 9 个测试 + 1 个表驱动 helper 测试。Mock NapCat 复用了 TestStart_FetchesSelfIDWithoutTimeout 的模式,单个 httptest.Server 同时承载 WS(receive + default send)和 HTTP(fallback 路径),每个 surface 用 atomic counter 记录调用次数以便断言。

验证

  • gofmt -l platform/qq/ — clean
  • go vet ./platform/qq/... — clean
  • go test ./platform/qq/... — all pass

不做什么

  • 不动 SendImage() / SendFile() 既有路径
  • 不修改 WS callAPI 的 15s timeout(HTTP 旁路才是 fix)
  • 不引入新依赖 / 新框架

Long replies (~2.5KB+) always tripped the hardcoded 15s timeout in
callAPI because the OneBot readLoop serves both inbound events and
outbound replies — long sends queue behind inbound traffic and stall.

New `send_via_http` config knob (default "auto"):

  - "auto"   → WS for <=512 byte messages, HTTP for longer ones.
               Falls back to WS when http_url is unset.
  - "always" → always HTTP (requires http_url); falls back to WS when
               absent so unconfigured deployments still deliver.
  - "never"  → always WebSocket, even for long messages.

SendFile() and SendImage() are unaffected — separate code paths.

Tests cover: short-msg WS path, long-msg HTTP fallback (2500B),
private-vs-group, threshold boundary, mode=always/never, auto with
no http_url, invalid config value (falls back to auto), and a
table-driven shouldUseHTTP test.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] QQ OneBot: Send() always uses WebSocket callAPI with 15s timeout — long group messages time out

1 participant