fix(feishu): isolate lark ws Client event loop from main asyncio loop
Commit 0209ad5 moved `import lark_oapi as lark` inside the start()
method (lazy import) to suppress DeprecationWarnings. This had an
unintended side effect: the import now happens after the main asyncio
loop is already running, so lark_oapi's module-level
loop = asyncio.get_event_loop()
captures the running main loop. When the WebSocket thread then calls
loop.run_until_complete() inside Client.start(), Python raises:
RuntimeError: This event loop is already running
and the _connect/_disconnect coroutines are never awaited.
Fix: in run_ws(), create a fresh event loop with asyncio.new_event_loop(),
set it as the thread's current loop, and patch lark_oapi.ws.client.loop
to point to this dedicated loop before calling Client.start(). The loop
is closed on thread exit.
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
This commit is contained in:
@@ -290,16 +290,28 @@ class FeishuChannel(BaseChannel):
|
|||||||
log_level=lark.LogLevel.INFO
|
log_level=lark.LogLevel.INFO
|
||||||
)
|
)
|
||||||
|
|
||||||
# Start WebSocket client in a separate thread with reconnect loop
|
# Start WebSocket client in a separate thread with reconnect loop.
|
||||||
|
# A dedicated event loop is created for this thread so that lark_oapi's
|
||||||
|
# module-level `loop = asyncio.get_event_loop()` picks up an idle loop
|
||||||
|
# instead of the already-running main asyncio loop, which would cause
|
||||||
|
# "This event loop is already running" errors.
|
||||||
def run_ws():
|
def run_ws():
|
||||||
|
import time
|
||||||
|
import lark_oapi.ws.client as _lark_ws_client
|
||||||
|
ws_loop = asyncio.new_event_loop()
|
||||||
|
asyncio.set_event_loop(ws_loop)
|
||||||
|
# Patch the module-level loop used by lark's ws Client.start()
|
||||||
|
_lark_ws_client.loop = ws_loop
|
||||||
|
try:
|
||||||
while self._running:
|
while self._running:
|
||||||
try:
|
try:
|
||||||
self._ws_client.start()
|
self._ws_client.start()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning("Feishu WebSocket error: {}", e)
|
logger.warning("Feishu WebSocket error: {}", e)
|
||||||
if self._running:
|
if self._running:
|
||||||
import time
|
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
|
finally:
|
||||||
|
ws_loop.close()
|
||||||
|
|
||||||
self._ws_thread = threading.Thread(target=run_ws, daemon=True)
|
self._ws_thread = threading.Thread(target=run_ws, daemon=True)
|
||||||
self._ws_thread.start()
|
self._ws_thread.start()
|
||||||
|
|||||||
Reference in New Issue
Block a user