refactor(scheduler/exceptions): 完善异常基类与子类的错误码和序列化能力
1. 为SchedulerError基类新增error_code类变量、trace_id参数和to_dict序列化方法 2. 为所有异常子类补充对应的业务错误码 3. 优化异常的字符串展示格式,增加error_code前缀
This commit is contained in:
parent
1003b842e1
commit
67d42fc246
@ -35,22 +35,48 @@ class SchedulerError(Exception):
|
|||||||
|
|
||||||
所有本上下文抛出的异常都应继承此类,最外层统一捕获后映射为 HTTP 响应。
|
所有本上下文抛出的异常都应继承此类,最外层统一捕获后映射为 HTTP 响应。
|
||||||
``status_code`` 作为异常到 HTTP 状态码的映射依据,子类按需覆盖。
|
``status_code`` 作为异常到 HTTP 状态码的映射依据,子类按需覆盖。
|
||||||
|
``error_code`` 作为稳定错误码,子类以类变量覆盖,用于驱动协议响应与日志关联。
|
||||||
|
``trace_id`` 用于跨链路追踪关联。
|
||||||
"""
|
"""
|
||||||
|
|
||||||
status_code: int = 500
|
status_code: int = 500
|
||||||
|
error_code: str = "SCHEDULER_ERROR"
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
message: str,
|
message: str,
|
||||||
*,
|
*,
|
||||||
details: dict[str, Any] | None = None,
|
details: dict[str, Any] | None = None,
|
||||||
|
trace_id: str | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
"""初始化异常实例。
|
||||||
|
|
||||||
|
参数:
|
||||||
|
message: 人类可读错误信息。
|
||||||
|
details: 业务字段字典,默认空字典。
|
||||||
|
trace_id: 调用链路追踪 ID,用于跨链路关联。
|
||||||
|
"""
|
||||||
super().__init__(message)
|
super().__init__(message)
|
||||||
self.message = message
|
self.message = message
|
||||||
self.details = details or {}
|
self.details = details or {}
|
||||||
|
self.trace_id = trace_id
|
||||||
|
|
||||||
|
def to_dict(self) -> dict[str, Any]:
|
||||||
|
"""序列化为字典,便于跨层传递、日志记录与 API 响应。
|
||||||
|
|
||||||
|
返回 ``error_code`` / ``message`` / ``trace_id`` 三个基础字段,
|
||||||
|
并展开 ``details`` 中的业务字段。
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
"error_code": self.error_code,
|
||||||
|
"message": self.message,
|
||||||
|
"trace_id": self.trace_id,
|
||||||
|
**self.details,
|
||||||
|
}
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.message
|
"""返回 ``[error_code] message`` 格式的字符串表示。"""
|
||||||
|
return f"[{self.error_code}] {self.message}"
|
||||||
|
|
||||||
|
|
||||||
# ─── 业务规则异常 ──────────────────────────────────────────────────────────
|
# ─── 业务规则异常 ──────────────────────────────────────────────────────────
|
||||||
@ -64,6 +90,7 @@ class SchedulerValidationError(SchedulerError, ValueError):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
status_code = 400
|
status_code = 400
|
||||||
|
error_code = "VALIDATION_ERROR"
|
||||||
|
|
||||||
|
|
||||||
class InvalidCronExpressionError(SchedulerValidationError):
|
class InvalidCronExpressionError(SchedulerValidationError):
|
||||||
@ -73,6 +100,8 @@ class InvalidCronExpressionError(SchedulerValidationError):
|
|||||||
``expression`` / ``field`` / ``reason`` 等定位信息。
|
``expression`` / ``field`` / ``reason`` 等定位信息。
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
error_code = "INVALID_CRON"
|
||||||
|
|
||||||
|
|
||||||
class SchedulerPayloadTooLargeError(SchedulerValidationError):
|
class SchedulerPayloadTooLargeError(SchedulerValidationError):
|
||||||
"""任务 payload 超过大小限制。
|
"""任务 payload 超过大小限制。
|
||||||
@ -82,6 +111,7 @@ class SchedulerPayloadTooLargeError(SchedulerValidationError):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
status_code = 413
|
status_code = 413
|
||||||
|
error_code = "PAYLOAD_TOO_LARGE"
|
||||||
|
|
||||||
|
|
||||||
class HandlerNotFoundError(SchedulerValidationError):
|
class HandlerNotFoundError(SchedulerValidationError):
|
||||||
@ -92,6 +122,8 @@ class HandlerNotFoundError(SchedulerValidationError):
|
|||||||
归入 ``SchedulerValidationError``。``details`` 可携带 ``handler_key``。
|
归入 ``SchedulerValidationError``。``details`` 可携带 ``handler_key``。
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
error_code = "HANDLER_NOT_FOUND"
|
||||||
|
|
||||||
|
|
||||||
# ─── 实体不存在 ──────────────────────────────────────────────────────────
|
# ─── 实体不存在 ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
@ -104,6 +136,7 @@ class SchedulerEntityNotFoundError(SchedulerError):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
status_code = 404
|
status_code = 404
|
||||||
|
error_code = "NOT_FOUND"
|
||||||
|
|
||||||
|
|
||||||
# ─── 权限 ────────────────────────────────────────────────────────────────
|
# ─── 权限 ────────────────────────────────────────────────────────────────
|
||||||
@ -117,6 +150,7 @@ class SchedulerPermissionDeniedError(SchedulerError):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
status_code = 403
|
status_code = 403
|
||||||
|
error_code = "PERMISSION_DENIED"
|
||||||
|
|
||||||
|
|
||||||
# ─── 冲突 ────────────────────────────────────────────────────────────────
|
# ─── 冲突 ────────────────────────────────────────────────────────────────
|
||||||
@ -130,6 +164,7 @@ class SchedulerConflictError(SchedulerError):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
status_code = 409
|
status_code = 409
|
||||||
|
error_code = "CONFLICT"
|
||||||
|
|
||||||
|
|
||||||
class DuplicateHandlerError(SchedulerConflictError):
|
class DuplicateHandlerError(SchedulerConflictError):
|
||||||
@ -139,6 +174,8 @@ class DuplicateHandlerError(SchedulerConflictError):
|
|||||||
``details`` 可携带 ``handler_key`` / ``existing_class``。
|
``details`` 可携带 ``handler_key`` / ``existing_class``。
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
error_code = "DUPLICATE_HANDLER"
|
||||||
|
|
||||||
|
|
||||||
class TaskStatusTransitionError(SchedulerConflictError):
|
class TaskStatusTransitionError(SchedulerConflictError):
|
||||||
"""任务状态机非法转换。
|
"""任务状态机非法转换。
|
||||||
@ -146,3 +183,5 @@ class TaskStatusTransitionError(SchedulerConflictError):
|
|||||||
由任务状态机在不允许的转换路径上抛出(如从 ``succeeded`` 转回 ``running``)。
|
由任务状态机在不允许的转换路径上抛出(如从 ``succeeded`` 转回 ``running``)。
|
||||||
``details`` 可携带 ``from_state`` / ``to_state`` / ``allowed_transitions``。
|
``details`` 可携带 ``from_state`` / ``to_state`` / ``allowed_transitions``。
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
error_code = "STATUS_TRANSITION_INVALID"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user