mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-05-21 09:02:32 +00:00
refactor(signal): wrap top-level receive handler with _safe_handle
Replace the inline try/except at the end of _handle_receive_notification with a small async context manager that swallows the exception, logs self.logger.error with the offending payload's repr (bounded to 200 chars), and attaches the traceback via logger.opt(exception=True). The previous log line only carried `e`, so diagnosing a bad envelope from production logs required correlating timestamps. The wrapper is generic so future receive/dispatch sites can adopt it; for now only this site uses it. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
1377759705
commit
971b774282
@ -8,7 +8,8 @@ import re
|
|||||||
import shutil
|
import shutil
|
||||||
import unicodedata
|
import unicodedata
|
||||||
from collections import deque
|
from collections import deque
|
||||||
from collections.abc import Callable
|
from collections.abc import AsyncIterator, Callable
|
||||||
|
from contextlib import asynccontextmanager
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
@ -557,10 +558,29 @@ class SignalChannel(BaseChannel):
|
|||||||
self.logger.error(f"Error in SSE receive loop: {e}")
|
self.logger.error(f"Error in SSE receive loop: {e}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
@asynccontextmanager
|
||||||
|
async def _safe_handle(
|
||||||
|
self, action: str, payload: Any = None
|
||||||
|
) -> AsyncIterator[None]:
|
||||||
|
"""Swallow and log any exception from a top-level handler block.
|
||||||
|
|
||||||
|
Logs `self.logger.error` with the action name, the exception, and a
|
||||||
|
bounded ``repr`` of the offending payload so the offending input is
|
||||||
|
recoverable from logs without having to correlate by timestamp.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
yield
|
||||||
|
except Exception as e:
|
||||||
|
snippet = repr(payload)[:200] if payload is not None else ""
|
||||||
|
text = f"Error in {action}: {e}"
|
||||||
|
if snippet:
|
||||||
|
text += f" | payload={snippet}"
|
||||||
|
self.logger.opt(exception=True).error(text)
|
||||||
|
|
||||||
async def _handle_receive_notification(self, params: dict[str, Any]) -> None:
|
async def _handle_receive_notification(self, params: dict[str, Any]) -> None:
|
||||||
"""Handle incoming message notification from signal-cli."""
|
"""Handle incoming message notification from signal-cli."""
|
||||||
self.logger.debug(f"_handle_receive_notification called with: {params}")
|
self.logger.debug(f"_handle_receive_notification called with: {params}")
|
||||||
try:
|
async with self._safe_handle("receive notification", params):
|
||||||
# Extract envelope from SSE notification: {"envelope": {...}}
|
# Extract envelope from SSE notification: {"envelope": {...}}
|
||||||
envelope = params.get("envelope", {})
|
envelope = params.get("envelope", {})
|
||||||
|
|
||||||
@ -613,9 +633,6 @@ class SignalChannel(BaseChannel):
|
|||||||
elif typing_message:
|
elif typing_message:
|
||||||
pass # Ignore typing indicators
|
pass # Ignore typing indicators
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
self.logger.error(f"Error handling receive notification: {e}")
|
|
||||||
|
|
||||||
async def _handle_data_message(
|
async def _handle_data_message(
|
||||||
self,
|
self,
|
||||||
sender_id: str,
|
sender_id: str,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user