2026-07-02 03:22:12 +08:00
|
|
|
|
"""控制面管道上下文。
|
|
|
|
|
|
|
|
|
|
|
|
定义控制面管道的可变局部上下文 ``ControlPlaneContext``,携带请求从 auth 到
|
|
|
|
|
|
audit 各阶段产生的状态。上下文为 ``@dataclass``(不 frozen),阶段直接修改
|
|
|
|
|
|
字段以推进管道状态。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
2026-07-03 19:18:13 +08:00
|
|
|
|
from collections.abc import Awaitable, Callable
|
|
|
|
|
|
from dataclasses import dataclass, field
|
2026-07-02 03:22:12 +08:00
|
|
|
|
from typing import TYPE_CHECKING, Any
|
|
|
|
|
|
|
2026-07-18 02:04:03 +08:00
|
|
|
|
from yuxi.channels.contract.dtos.audit.audit import AuditTxStrategy
|
|
|
|
|
|
from yuxi.channels.contract.dtos.messaging.channel import ChannelType
|
|
|
|
|
|
from yuxi.channels.contract.dtos.messaging.common import Operator
|
|
|
|
|
|
from yuxi.channels.contract.dtos.shared.control import ControlPlaneResult
|
2026-07-02 03:22:12 +08:00
|
|
|
|
from yuxi.channels.contract.errors import Error
|
|
|
|
|
|
|
|
|
|
|
|
if TYPE_CHECKING:
|
2026-07-18 02:04:03 +08:00
|
|
|
|
from yuxi.channels.contract.ports.driven.shared.transaction_port import TransactionContext
|
2026-07-02 03:22:12 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
|
|
class ControlPlaneContext:
|
|
|
|
|
|
"""控制面管道可变局部上下文。
|
|
|
|
|
|
|
|
|
|
|
|
携带控制面请求从 auth 到 audit 各阶段产生的状态,阶段按顺序填充字段。
|
|
|
|
|
|
字段按阶段分组,便于追溯状态来源。
|
|
|
|
|
|
|
|
|
|
|
|
事务边界(§10.1):``tx`` 字段由 ``ChannelControlService`` 在管道
|
|
|
|
|
|
执行前通过 ``TransactionPort.begin()`` 开启,dispatch 与 audit 阶段
|
|
|
|
|
|
的写操作共享此事务上下文。``audit_tx_strategy`` 由 dispatch 阶段
|
|
|
|
|
|
根据操作副作用可回滚性设置:SHARED 策略下 audit 共享事务(fail-closed,
|
|
|
|
|
|
FR-34),INDEPENDENT 策略下 audit 使用独立事务(best-effort,适用于
|
|
|
|
|
|
已产生不可回滚外部副作用的操作)。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
# ---- 基础字段 ----
|
|
|
|
|
|
trace_id: str
|
|
|
|
|
|
request_id: str
|
|
|
|
|
|
operator: Operator
|
|
|
|
|
|
operation: str
|
|
|
|
|
|
params: dict[str, Any]
|
|
|
|
|
|
target_channel: ChannelType | None = None
|
|
|
|
|
|
|
|
|
|
|
|
# ---- 事务上下文(由 ChannelControlService 注入,dispatch/audit 共享)----
|
|
|
|
|
|
tx: TransactionContext | None = None
|
|
|
|
|
|
|
|
|
|
|
|
# ---- auth 阶段字段 ----
|
|
|
|
|
|
authenticated: bool = False
|
|
|
|
|
|
|
|
|
|
|
|
# ---- permission 阶段字段 ----
|
|
|
|
|
|
permission_granted: bool = False
|
|
|
|
|
|
required_permission: str | None = None
|
|
|
|
|
|
|
|
|
|
|
|
# ---- rate-limit 阶段字段 ----
|
|
|
|
|
|
rate_limit_passed: bool = False
|
|
|
|
|
|
|
|
|
|
|
|
# ---- dispatch 阶段字段 ----
|
2026-07-09 04:21:28 +08:00
|
|
|
|
dispatch_result: ControlPlaneResult | None = None
|
2026-07-02 03:22:12 +08:00
|
|
|
|
# dispatch 阶段幂等短路标记:当操作命中幂等条件(如 account/enable
|
|
|
|
|
|
# 对已启用账户)时,handler 未执行任何状态变更即提前返回,设置为 True
|
|
|
|
|
|
# 通知 audit 阶段跳过"状态变更类"审计写入,避免幂等请求被误记为
|
|
|
|
|
|
# 实际状态变更(§10.1 审计精确性)。
|
|
|
|
|
|
dispatch_skipped: bool = False
|
2026-07-03 19:18:13 +08:00
|
|
|
|
# dispatch 阶段部分成功标记:批量操作(如 message/batch_recall)中
|
|
|
|
|
|
# 部分目标成功、部分失败时由 handler 设置为 True,供
|
|
|
|
|
|
# ``ChannelControlService._executeControl`` 构造
|
|
|
|
|
|
# ``ControlResult(status="partial")``,使响应 envelope 能准确反映
|
|
|
|
|
|
# 部分成功语义,避免外层 ``success: True`` 误导客户端。
|
|
|
|
|
|
dispatch_partial: bool = False
|
2026-07-02 03:22:12 +08:00
|
|
|
|
|
|
|
|
|
|
# ---- audit 阶段字段 ----
|
|
|
|
|
|
audit_logged: bool = False
|
|
|
|
|
|
# dispatch 阶段根据操作副作用可回滚性设置(§10.1 事务边界)
|
|
|
|
|
|
audit_tx_strategy: AuditTxStrategy = AuditTxStrategy.SHARED
|
|
|
|
|
|
# INDEPENDENT 策略下 audit 写入失败时的错误(best-effort,由
|
|
|
|
|
|
# ChannelControlService 记录告警,不中止业务)
|
|
|
|
|
|
audit_error: Error | None = None
|
|
|
|
|
|
|
|
|
|
|
|
# ---- 降级标志字段 ----
|
|
|
|
|
|
degraded: bool = False
|
|
|
|
|
|
degraded_reason: Error | None = None
|
2026-07-03 19:18:13 +08:00
|
|
|
|
|
|
|
|
|
|
# ---- 事务后副作用钩子(dispatch 阶段注册,由 ChannelControlService
|
|
|
|
|
|
# 在事务提交成功后执行)。用于处理"DB 写入可回滚 + 外部副作用不可回滚"
|
|
|
|
|
|
# 混合场景:将不可回滚的外部副作用(如 ARQ 任务入队)推迟到事务提交后
|
|
|
|
|
|
# 执行,避免事务回滚时产生孤儿副作用(§10.1 事务边界)。
|
|
|
|
|
|
post_commit_hooks: list[Callable[[], Awaitable[None]]] = field(default_factory=list)
|