本次提交包含多类改进: 1. 清理冗余空行、修复导入格式与类型检查占位 2. 新增external_systems与scheduler上下文的handler注册框架 3. 补全调度器相关配置项与环境变量覆盖逻辑 4. 新增配置校验与敏感字段脱敏逻辑 5. 简化协议方法声明格式
134 lines
4.7 KiB
Python
134 lines
4.7 KiB
Python
"""ORM ↔ dataclass 映射边界。
|
||
|
||
本模块是 ``adapters/persistence`` 层负责 ORM 实例 ↔ core dataclass 转换的位置。
|
||
scheduler 限界上下文无敏感字段,mapper 仅做字段映射,不调用 ``encrypt`` /
|
||
``decrypt``(与 ``external_systems/adapters/persistence/mappers.py`` 不同)。
|
||
|
||
设计原则(见设计方案 §10):
|
||
|
||
- **mapper 不调用 ORM 的 ``to_dict`` 方法**:直接读 ORM 字段构造 dataclass。
|
||
原因:``to_dict`` 返回的 dict 结构与 dataclass 字段不完全一致(如 DateTime
|
||
字段在 ``to_dict`` 中被 ``format_utc_datetime`` 格式化为字符串)。
|
||
- **无敏感字段**:scheduler 域所有字段均为明文存储,无需加解密。
|
||
- **处理 None 入参**:ORM 实例为 None 时返回 None,避免调用方需额外判空。
|
||
- **仓储层 dataclass → core dataclass**:``DailyStat`` / ``HandlerSummary`` 在
|
||
仓储层与 core 层均有同名 dataclass,mapper 按字段名转换。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from typing import TYPE_CHECKING, Any
|
||
|
||
from yuxi.scheduler.core.models import (
|
||
DailyStat as DailyStatDC,
|
||
)
|
||
from yuxi.scheduler.core.models import (
|
||
HandlerSummary as HandlerSummaryDC,
|
||
)
|
||
from yuxi.scheduler.core.models import (
|
||
ScheduledTask as ScheduledTaskDC,
|
||
)
|
||
from yuxi.scheduler.core.models import (
|
||
ScheduledTaskRunLog as ScheduledTaskRunLogDC,
|
||
)
|
||
|
||
if TYPE_CHECKING:
|
||
from yuxi.storage.postgres.models_scheduler import (
|
||
ScheduledTask as ScheduledTaskORM,
|
||
)
|
||
from yuxi.storage.postgres.models_scheduler import (
|
||
ScheduledTaskRunLog as ScheduledTaskRunLogORM,
|
||
)
|
||
|
||
|
||
def orm_to_task(orm: ScheduledTaskORM | None) -> ScheduledTaskDC | None:
|
||
"""ORM → dataclass,``ScheduledTask`` 字段一一映射。
|
||
|
||
DateTime 字段直接赋值(core 用 ``Any``),JSON 字段直接赋值。
|
||
入参为 None 时返回 None,避免调用方需额外判空。
|
||
"""
|
||
if orm is None:
|
||
return None
|
||
return ScheduledTaskDC(
|
||
id=orm.id,
|
||
task_id=orm.task_id,
|
||
handler_name=orm.handler_name,
|
||
owner_scope=orm.owner_scope,
|
||
owner_id=orm.owner_id,
|
||
schedule_kind=orm.schedule_kind,
|
||
cron_expression=orm.cron_expression,
|
||
run_at=orm.run_at,
|
||
tz=orm.tz,
|
||
payload=orm.payload or {},
|
||
enabled=orm.enabled,
|
||
delete_after_run=orm.delete_after_run,
|
||
block_strategy=orm.block_strategy,
|
||
stagger_seconds=orm.stagger_seconds,
|
||
consecutive_errors=orm.consecutive_errors,
|
||
status=orm.status,
|
||
last_run_at=orm.last_run_at,
|
||
next_run_at=orm.next_run_at,
|
||
last_error=orm.last_error,
|
||
created_by=orm.created_by,
|
||
updated_by=orm.updated_by,
|
||
created_at=orm.created_at,
|
||
updated_at=orm.updated_at,
|
||
is_deleted=orm.is_deleted,
|
||
deleted_at=orm.deleted_at,
|
||
)
|
||
|
||
|
||
def orm_to_run_log(orm: ScheduledTaskRunLogORM | None) -> ScheduledTaskRunLogDC | None:
|
||
"""ORM → dataclass,``ScheduledTaskRunLog`` 字段一一映射。
|
||
|
||
入参为 None 时返回 None,避免调用方需额外判空。
|
||
"""
|
||
if orm is None:
|
||
return None
|
||
return ScheduledTaskRunLogDC(
|
||
id=orm.id,
|
||
task_id=orm.task_id,
|
||
run_id=orm.run_id,
|
||
triggered_by=orm.triggered_by,
|
||
status=orm.status,
|
||
error_message=orm.error_message,
|
||
output=orm.output,
|
||
started_at=orm.started_at,
|
||
finished_at=orm.finished_at,
|
||
created_by=orm.created_by,
|
||
updated_by=orm.updated_by,
|
||
created_at=orm.created_at,
|
||
updated_at=orm.updated_at,
|
||
is_deleted=orm.is_deleted,
|
||
deleted_at=orm.deleted_at,
|
||
)
|
||
|
||
|
||
def daily_stat_row_to_dataclass(row: Any) -> DailyStatDC:
|
||
"""仓储层 ``DailyStat`` → core ``DailyStat`` dataclass,按字段名映射。
|
||
|
||
仓储层 ``DailyStat`` 是 dataclass,row 可能是 NamedTuple 或 dataclass 实例,
|
||
统一按字段名读取并转换为 core dataclass。
|
||
"""
|
||
return DailyStatDC(
|
||
stat_date=row.stat_date,
|
||
handler_name=row.handler_name,
|
||
success_count=int(row.success_count),
|
||
failure_count=int(row.failure_count),
|
||
timeout_count=int(row.timeout_count),
|
||
dead_letter_count=int(row.dead_letter_count),
|
||
)
|
||
|
||
|
||
def handler_summary_row_to_dataclass(row: Any) -> HandlerSummaryDC:
|
||
"""仓储层 ``HandlerSummary`` → core ``HandlerSummary`` dataclass,按字段名映射。
|
||
|
||
仓储层 ``HandlerSummary`` 是 dataclass,row 可能是 NamedTuple 或 dataclass 实例,
|
||
统一按字段名读取并转换为 core dataclass。
|
||
"""
|
||
return HandlerSummaryDC(
|
||
name=row.name,
|
||
task_count=int(row.task_count),
|
||
last_active_at=row.last_active_at,
|
||
)
|