ForcePilot/backend/package/yuxi/channel/extensions/matrix/errors.py

65 lines
1.7 KiB
Python
Raw Normal View History

from __future__ import annotations
import logging
from yuxi.channel.protocols import ClassifiedError, ErrorSeverity
logger = logging.getLogger(__name__)
def classify_error(error: BaseException) -> ClassifiedError:
msg = str(error).upper()
if "M_LIMIT_EXCEEDED" in msg or "429" in str(error):
return ClassifiedError(
severity=ErrorSeverity.RATE_LIMITED,
retry_after_ms=_extract_retry_after(error),
original_error=error,
error_message=str(error),
)
if any(kw in msg for kw in ("M_UNKNOWN_TOKEN", "M_MISSING_TOKEN", "M_NOT_JSON")):
return ClassifiedError(
severity=ErrorSeverity.FORBIDDEN,
original_error=error,
error_message=str(error),
)
if "M_FORBIDDEN" in msg:
return ClassifiedError(
severity=ErrorSeverity.FORBIDDEN,
original_error=error,
error_message=str(error),
)
if "M_NOT_FOUND" in msg:
return ClassifiedError(
severity=ErrorSeverity.FATAL,
original_error=error,
error_message=str(error),
)
if isinstance(error, (ConnectionError, TimeoutError, OSError)):
return ClassifiedError(
severity=ErrorSeverity.NETWORK,
original_error=error,
error_message=str(error),
)
return ClassifiedError(
severity=ErrorSeverity.FATAL,
original_error=error,
error_message=str(error),
)
def _extract_retry_after(error) -> int:
try:
import re
m = re.search(r"retry_after_ms[:\s]+(\d+)", str(error), re.IGNORECASE)
if m:
return int(m.group(1))
except (ValueError, TypeError):
pass
return 5000