本次提交新增了通道模块的完整基础实现: 1. 搭建了channel包的顶层导出结构,整合所有核心子模块接口 2. 实现了错误处理工具类与重试退避逻辑 3. 新增UI表单/页面/字段的schema定义与自动生成工具 4. 完成上下文管理模块,支持会话上下文、可见性过滤与运行时状态注册 5. 实现通道能力配置类,支持流式传输、功能开关等多维度能力定义
85 lines
2.4 KiB
Python
85 lines
2.4 KiB
Python
from __future__ import annotations
|
|
|
|
import logging
|
|
from typing import Any
|
|
|
|
from yuxi.channel.protocols import ClassifiedError, ErrorSeverity, ErrorHandlingProtocol
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def capture_error(
|
|
logger_instance: logging.Logger,
|
|
error: BaseException,
|
|
*,
|
|
message: str = "",
|
|
context: dict[str, Any] | None = None,
|
|
level: str = "error",
|
|
) -> ClassifiedError:
|
|
if level == "warning":
|
|
logger_instance.warning(
|
|
"%s: %s | context=%s",
|
|
message or "Operation failed",
|
|
error,
|
|
context or {},
|
|
exc_info=True,
|
|
)
|
|
else:
|
|
logger_instance.exception(message or "Operation failed")
|
|
|
|
return ClassifiedError(
|
|
severity=_infer_severity(error),
|
|
original_error=error,
|
|
error_message=str(error),
|
|
)
|
|
|
|
|
|
def classify_error(error: BaseException) -> ClassifiedError:
|
|
return ClassifiedError(
|
|
severity=_infer_severity(error),
|
|
original_error=error,
|
|
error_message=str(error),
|
|
)
|
|
|
|
|
|
def is_retryable(error: BaseException) -> bool:
|
|
return _infer_severity(error) == ErrorSeverity.RETRYABLE
|
|
|
|
|
|
def should_backoff(error: BaseException, attempt: int) -> int:
|
|
if not is_retryable(error):
|
|
return 0
|
|
base_ms = 1000
|
|
max_ms = 30000
|
|
delay_ms = min(base_ms * (2 ** (attempt - 1)), max_ms)
|
|
return delay_ms
|
|
|
|
|
|
def _infer_severity(error: BaseException) -> ErrorSeverity:
|
|
import asyncio
|
|
import builtins
|
|
|
|
if isinstance(error, asyncio.TimeoutError):
|
|
return ErrorSeverity.NETWORK
|
|
if isinstance(error, builtins.TimeoutError):
|
|
return ErrorSeverity.NETWORK
|
|
if isinstance(error, ConnectionError):
|
|
return ErrorSeverity.NETWORK
|
|
if isinstance(error, PermissionError):
|
|
return ErrorSeverity.FORBIDDEN
|
|
if isinstance(error, (ValueError, TypeError, KeyError, IndexError, AttributeError)):
|
|
return ErrorSeverity.FATAL
|
|
if isinstance(error, asyncio.CancelledError):
|
|
return ErrorSeverity.FATAL
|
|
return ErrorSeverity.RETRYABLE
|
|
|
|
|
|
class DefaultErrorHandler(ErrorHandlingProtocol):
|
|
def classify_error(self, error: BaseException) -> ClassifiedError:
|
|
return classify_error(error)
|
|
|
|
def is_retryable(self, error: BaseException) -> bool:
|
|
return is_retryable(error)
|
|
|
|
def should_backoff(self, error: BaseException, attempt: int) -> int:
|
|
return should_backoff(error, attempt) |