172 lines
4.8 KiB
Python
172 lines
4.8 KiB
Python
|
|
"""服务端错误类型定义。
|
|||
|
|
|
|||
|
|
定义 ``ServerError`` 抽象基类及其 4 个具体子类,表示由服务端引起的错误
|
|||
|
|
(5xx 语义):内部错误、依赖故障、超时、未实现。``ServerError`` 额外携带
|
|||
|
|
``cause`` 字段记录原始错误,便于追踪。
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
from __future__ import annotations
|
|||
|
|
|
|||
|
|
from typing import Any
|
|||
|
|
|
|||
|
|
from yuxi.channels.contract.errors.base import Error
|
|||
|
|
|
|||
|
|
|
|||
|
|
class ServerError(Error):
|
|||
|
|
"""服务端错误抽象基类。
|
|||
|
|
|
|||
|
|
表示由服务端引起的错误(5xx 语义)。额外携带 ``cause`` 字段记录原始错误,
|
|||
|
|
便于跨链路追踪。子类包括 ``InternalError`` / ``DependencyError`` /
|
|||
|
|
``TimeoutError``。
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
error_code = "SERVER_ERROR"
|
|||
|
|
|
|||
|
|
def __init__(
|
|||
|
|
self,
|
|||
|
|
message: str,
|
|||
|
|
*,
|
|||
|
|
trace_id: str | None = None,
|
|||
|
|
cause: Error | Exception | None = None,
|
|||
|
|
) -> None:
|
|||
|
|
super().__init__(message, trace_id=trace_id)
|
|||
|
|
self.cause = cause
|
|||
|
|
|
|||
|
|
def to_dict(self) -> dict[str, Any]:
|
|||
|
|
data = super().to_dict()
|
|||
|
|
if self.cause is None:
|
|||
|
|
data["cause"] = None
|
|||
|
|
elif isinstance(self.cause, Error):
|
|||
|
|
data["cause"] = self.cause.to_dict()
|
|||
|
|
else:
|
|||
|
|
# 原生 Exception 无 to_dict(),仅记录类型与信息以便追踪
|
|||
|
|
data["cause"] = {
|
|||
|
|
"type": type(self.cause).__name__,
|
|||
|
|
"message": str(self.cause),
|
|||
|
|
}
|
|||
|
|
return data
|
|||
|
|
|
|||
|
|
|
|||
|
|
class InternalError(ServerError):
|
|||
|
|
"""内部错误。
|
|||
|
|
|
|||
|
|
服务端内部异常导致的错误(HTTP 500)。``cause`` 可选:当原始错误为
|
|||
|
|
``Error`` 子类时传入以保留结构化错误链;当原始错误为原生 ``Exception``
|
|||
|
|
时可不传 ``cause``,通过 ``message`` 携带异常信息。
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
error_code = "INTERNAL"
|
|||
|
|
|
|||
|
|
def __init__(
|
|||
|
|
self,
|
|||
|
|
cause: Error | Exception | None = None,
|
|||
|
|
*,
|
|||
|
|
trace_id: str | None = None,
|
|||
|
|
message: str | None = None,
|
|||
|
|
) -> None:
|
|||
|
|
super().__init__(
|
|||
|
|
message or "Internal error",
|
|||
|
|
trace_id=trace_id,
|
|||
|
|
cause=cause,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
|
|||
|
|
class DependencyError(ServerError):
|
|||
|
|
"""依赖故障错误。
|
|||
|
|
|
|||
|
|
外部依赖(如数据库、Redis、第三方服务)故障时抛出(HTTP 502)。
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
error_code = "DEPENDENCY"
|
|||
|
|
|
|||
|
|
def __init__(
|
|||
|
|
self,
|
|||
|
|
dep: str,
|
|||
|
|
cause: Error | Exception,
|
|||
|
|
*,
|
|||
|
|
trace_id: str | None = None,
|
|||
|
|
) -> None:
|
|||
|
|
super().__init__(
|
|||
|
|
f"Dependency {dep} failed",
|
|||
|
|
trace_id=trace_id,
|
|||
|
|
cause=cause,
|
|||
|
|
)
|
|||
|
|
self.dep = dep
|
|||
|
|
|
|||
|
|
def to_dict(self) -> dict[str, Any]:
|
|||
|
|
data = super().to_dict()
|
|||
|
|
data["dep"] = self.dep
|
|||
|
|
return data
|
|||
|
|
|
|||
|
|
|
|||
|
|
class TimeoutError(ServerError):
|
|||
|
|
"""超时错误。
|
|||
|
|
|
|||
|
|
操作超时时抛出(HTTP 504)。在 ``server`` 模块内覆盖 Python 内置
|
|||
|
|
``TimeoutError``,使用时通过模块路径或显式导入避免歧义。
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
error_code = "TIMEOUT"
|
|||
|
|
|
|||
|
|
def __init__(
|
|||
|
|
self,
|
|||
|
|
timeout_ms: int,
|
|||
|
|
*,
|
|||
|
|
message: str | None = None,
|
|||
|
|
trace_id: str | None = None,
|
|||
|
|
) -> None:
|
|||
|
|
"""初始化超时错误。
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
timeout_ms: 超时毫秒数,写入 ``details`` 供客户端参考。
|
|||
|
|
message: 自定义错误信息。为 ``None`` 时使用默认模板
|
|||
|
|
``"Operation timed out after {timeout_ms}ms"``。
|
|||
|
|
trace_id: 调用链路追踪 ID,用于跨链路关联。
|
|||
|
|
"""
|
|||
|
|
super().__init__(
|
|||
|
|
message or f"Operation timed out after {timeout_ms}ms",
|
|||
|
|
trace_id=trace_id,
|
|||
|
|
)
|
|||
|
|
self.timeout_ms = timeout_ms
|
|||
|
|
|
|||
|
|
def to_dict(self) -> dict[str, Any]:
|
|||
|
|
data = super().to_dict()
|
|||
|
|
data["timeout_ms"] = self.timeout_ms
|
|||
|
|
return data
|
|||
|
|
|
|||
|
|
|
|||
|
|
class NotImplementedError(ServerError):
|
|||
|
|
"""未实现错误。
|
|||
|
|
|
|||
|
|
请求的操作尚未实现时抛出(HTTP 501)。用于标记尚未落地的功能分支,
|
|||
|
|
避免静默返回空结果掩盖功能缺失。
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
error_code = "NOT_IMPLEMENTED"
|
|||
|
|
|
|||
|
|
def __init__(
|
|||
|
|
self,
|
|||
|
|
operation: str,
|
|||
|
|
*,
|
|||
|
|
message: str | None = None,
|
|||
|
|
trace_id: str | None = None,
|
|||
|
|
) -> None:
|
|||
|
|
"""初始化未实现错误。
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
operation: 未实现的操作名称,写入 ``details`` 供客户端参考。
|
|||
|
|
message: 自定义错误信息。为 ``None`` 时使用默认模板
|
|||
|
|
``"Operation not implemented: {operation}"``。
|
|||
|
|
trace_id: 调用链路追踪 ID,用于跨链路关联。
|
|||
|
|
"""
|
|||
|
|
super().__init__(
|
|||
|
|
message or f"Operation not implemented: {operation}",
|
|||
|
|
trace_id=trace_id,
|
|||
|
|
)
|
|||
|
|
self.operation = operation
|
|||
|
|
|
|||
|
|
def to_dict(self) -> dict[str, Any]:
|
|||
|
|
data = super().to_dict()
|
|||
|
|
data["operation"] = self.operation
|
|||
|
|
return data
|