本次提交包含多项代码优化与规范修正: 1. 文档与注释优化:修正注释术语、补充注解与FR编号 2. 代码格式调整:统一空格、换行与缩进规范 3. 类型与接口完善:补充__all__导出、修正返回类型注解 4. 错误处理增强:新增领域错误类与校验逻辑 5. 依赖与导入调整:修复路径引用、统一时区导入 6. 协议与契约更新:完善接口文档与一致性注解
72 lines
2.4 KiB
Python
72 lines
2.4 KiB
Python
"""优雅降级 DTO。
|
||
|
||
定义优雅降级(FR-36)的枚举与不可变值对象,包括降级等级与恢复状态。
|
||
所有枚举继承 ``str, Enum`` 以支持 JSON 序列化,DTO 均为
|
||
``dataclass(frozen=True)``,仅依赖标准库,用于插件失败后的降级状态
|
||
管理与恢复追踪。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from dataclasses import dataclass
|
||
from datetime import datetime
|
||
from enum import StrEnum
|
||
|
||
from yuxi.channels.contract.errors import ValidationError
|
||
|
||
|
||
class DegradationLevel(StrEnum):
|
||
"""降级等级。
|
||
|
||
标识系统或渠道的降级状态,用于健康检查与降级决策。继承
|
||
``str, Enum`` 以支持 JSON 序列化与字符串比较。
|
||
|
||
取值:
|
||
HEALTHY: 所有插件运行正常。
|
||
DEGRADED: 部分插件失败但核心功能可用。
|
||
UNHEALTHY: 核心插件失败或数据库 / Redis 不可用。
|
||
"""
|
||
|
||
HEALTHY = "healthy"
|
||
DEGRADED = "degraded"
|
||
UNHEALTHY = "unhealthy"
|
||
|
||
|
||
@dataclass(frozen=True)
|
||
class RecoveryStatus:
|
||
"""恢复状态。
|
||
|
||
描述失败插件的恢复追踪状态,包括插件 ID、重试次数、上次重试时间、
|
||
下次重试时间、是否已恢复与失败原因,用于 FR-36 优雅降级的恢复
|
||
流程管理与诊断。
|
||
|
||
字段:
|
||
plugin_id: 插件 ID。
|
||
retry_count: 重试次数(默认 0,上限 3)。
|
||
last_retry_at: 上次重试时间(可选)。
|
||
next_retry_at: 下次重试时间(可选)。
|
||
recovered: 是否已恢复(默认 False)。
|
||
failure_reason: 失败原因(可选,便于诊断)。
|
||
"""
|
||
|
||
plugin_id: str
|
||
retry_count: int = 0
|
||
last_retry_at: datetime | None = None
|
||
next_retry_at: datetime | None = None
|
||
recovered: bool = False
|
||
failure_reason: str | None = None
|
||
|
||
def __post_init__(self) -> None:
|
||
"""校验 plugin_id 非空与 retry_count 范围。
|
||
|
||
``plugin_id`` 必须非空,``retry_count`` 必须在 0-3 之间(FR-36 上限 3),
|
||
在构造时即抛出 ``ValidationError``,adapter 不再做该校验(INV-8)。
|
||
"""
|
||
if not self.plugin_id:
|
||
raise ValidationError("plugin_id", "must not be empty")
|
||
if self.retry_count < 0 or self.retry_count > 3:
|
||
raise ValidationError(
|
||
"retry_count",
|
||
"retry_count must be in [0, 3]",
|
||
)
|