fix(feishu): notify gateway reconnect watcher on WS thread death - #73202
fix(feishu): notify gateway reconnect watcher on WS thread death#73202zhaomengfan wants to merge 2 commits into
Conversation
Related: #31386 repairs the same Feishu WebSocket exit path with bounded adapter-level retries before escalation. This patch immediately notifies the gateway watcher instead; please choose one recovery policy rather than treating the implementations as duplicates. |
|
@alt-glitch This PR intentionally takes the "notify watcher immediately" approach rather than bounded adapter-level retries, following @teknium1's review guidance on #31367:
This PR also targets the current plugin adapter location ( |
Why this approach subsumes #313861. Reviewer already decided this@teknium1's review of #31386 (May 2026) is explicit:
This PR is the implementation of that directive. #31386 has not been updated since that review — it still carries a 5-retry exponential-backoff ladder (~31s) before escalating to the same supervisor. 2. No duplicate retry policyThe gateway supervisor (
3. Correct file location#31386 targets 4. Code surface+41 lines here vs +449 lines (+13 tests) in #31386 for the same failure detection. Simpler fix, fewer edge cases. 5. New production evidence (#73779)pittosporum-seu's report demonstrates the failure is a two-layer problem:
Both are needed. This PR closes the recovery gap with the approach the reviewer explicitly requested. Summary: If the team prefers bounded retries over immediate watcher escalation, that's a policy decision for the supervisor — not a reason to maintain two competing adapter-level implementations. This PR is the minimal, reviewer-aligned fix for the recovery gap. |
|
Thanks for keeping recovery in the gateway-owned reconnect path. The premise is present on current main: Problems
Suggested changes
This is an automated hermes-sweeper review. |
Duplicate of #53508 — both current patches add the same WebSocket-future completion callback and hand unexpected exits to the gateway reconnect watcher. |
Correction: related to #53508, not a duplicate. Current #73202 is the focused plugin-path supervisor-notification repair; #53508 bundles a related callback with unrelated Feishu behavior changes. #31386 uses a distinct adapter-level retry policy on the retired path. |
0a92b64 to
fbe1a82
Compare
fbe1a82 to
560e6e5
Compare
|
@teknium1 rebased onto latest This implements the recovery policy requested on #31386/#31367: unexpected WS thread exit routes through |
|
The latest public reproduction added to #31367 supports the recovery gap this PR addresses. This should remain the focused recovery-layer patch; #64247 addresses the multiplex event-loop root cause. The current PR metadata reports it as non-mergeable against current |
When Feishu's hosted WebSocket receive loop dies (~every 30 min), the lark-oapi SDK's ws_client.start() returns silently and the executor future completes with no observer. Without this fix, the adapter never learns the WS died, and when all platform connections drop simultaneously (multiplex with 5 profiles), the gateway's stranded-detection path triggers a full gateway restart — disconnecting every other platform and pausing all cron jobs. This change adds a done-callback on _ws_future that detects unexpected WS thread exit (distinct from clean disconnect where _running=False and _ws_client is cleared). On unexpected death, it calls _set_fatal_error(retryable=True) + _notify_fatal_error(), routing through the gateway's existing per-platform reconnect watcher instead of implementing its own retry loop. Fixes: NousResearch#31386 Refs: PR NousResearch#31367 (original fix, blocked by plugin-migration review)
Add 5 tests covering _handle_ws_unexpected_exit and _on_ws_thread_exit: - _handle_ws_unexpected_exit notifies fatal handler (retryable) - Gate: no-op when _running=False - Gate: no-op when _ws_client=None - _on_ws_thread_exit gate: clean-disconnect no-ops - _on_ws_thread_exit dispatches to loop
560e6e5 to
6c85b83
Compare
|
Thanks for rebasing and adding the requested tests. This now covers the recovery layer described in #31367: unexpected WS thread death is reported as retryable to the per-platform supervisor, while clean disconnect remains a no-op. The current CI checks are green and the branch is mergeable. Small metadata correction: the Related section currently reverses the two references:
Could you update it to:
This keeps attribution for the problem report and the original implementation distinct. |
|
@Seekers2001 thanks for catching that — updated. The Related section now reads:
Appreciate the review. |
What does this PR do?
When Feishu's hosted WebSocket receive loop dies (~every 30 min), the lark-oapi SDK's
ws_client.start()returns silently and the executor future completes with no observer. Without this fix, the adapter never learns the WS died, and when all platform connections drop simultaneously (multiplex with 5 profiles), the gateway's stranded-detection path triggers a full gateway restart — disconnecting every other platform and pausing all cron jobs.This change adds a
_on_ws_thread_exitdone-callback on_ws_futurethat detects unexpected WS thread exit (distinct from clean disconnect where_running=Falseand_ws_clientis cleared). On unexpected death, it calls_set_fatal_error(retryable=True)+_notify_fatal_error(), routing through the gateway's existing per-platform reconnect watcher — no custom retry loop, as requested in the #31367 review.Changes
plugins/platforms/feishu/adapter.py: +41 lines_on_ws_thread_exit()— done-callback that filters clean-disconnect from unexpected death_handle_ws_unexpected_exit()— cleanup + fatal-error notification_connect_websocket()viaadd_done_callbackHow to Test
Reproduce: run multiplex gateway with 5 Feishu profiles, wait ~30 min for WS receive-loop death.
Expected behaviour after fix:
Other platforms stay up, cron jobs not paused, active sessions not interrupted.
Related
Fixes #31367
Supersedes/ports #31386 (original fix by @xxxigm; this ports it to the plugin adapter location and routes through the existing gateway watcher per @teknium1's review)