mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-08-28 19:47:41 +08:00
117 lines
3.2 KiB
Python
117 lines
3.2 KiB
Python
"""事件 payload 的只读契约快照访问。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from typing import Any
|
|
|
|
from pydantic import BaseModel, ValidationError
|
|
|
|
from app.runtime.event.contracts import get_event_contract, normalize_event_type
|
|
from app.schemas.types import ChainEventType, EventType
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class EventPayloadSnapshot:
|
|
"""保存原始 payload 及按登记契约解析出的独立快照。"""
|
|
|
|
event_type: EventType | ChainEventType | str
|
|
raw: Any
|
|
payload: BaseModel | None
|
|
input: BaseModel | None
|
|
output: BaseModel | None
|
|
known: bool
|
|
schema_version: int | None
|
|
payload_mode: str | None
|
|
validation_mode: str | None
|
|
errors: tuple[str, ...] = ()
|
|
|
|
@property
|
|
def valid(self) -> bool:
|
|
"""返回已知事件的全部登记模型是否都通过校验。"""
|
|
return self.known and not self.errors
|
|
|
|
|
|
def _model_snapshot(
|
|
model: type[BaseModel] | None,
|
|
payload: Any,
|
|
label: str,
|
|
cache: dict[type[BaseModel], BaseModel | None],
|
|
errors: list[str],
|
|
) -> BaseModel | None:
|
|
"""按单个模型构造快照,同一模型在一次访问中只解析一次。"""
|
|
if model is None:
|
|
return None
|
|
if model in cache:
|
|
return cache[model]
|
|
if isinstance(payload, model):
|
|
cache[model] = payload.model_copy(deep=True)
|
|
return cache[model]
|
|
try:
|
|
cache[model] = model.model_validate(payload)
|
|
except (ValidationError, TypeError, ValueError) as error:
|
|
cache[model] = None
|
|
errors.append(f"{label}:{model.__name__}: {error}")
|
|
return cache[model]
|
|
|
|
|
|
def snapshot_event_data(
|
|
event_type: EventType | ChainEventType | str,
|
|
event_data: Any,
|
|
) -> EventPayloadSnapshot:
|
|
"""按事件注册契约解析 payload,未知自定义事件保持原始数据并返回未登记状态。"""
|
|
normalized = normalize_event_type(event_type)
|
|
try:
|
|
contract = get_event_contract(normalized)
|
|
except KeyError:
|
|
return EventPayloadSnapshot(
|
|
event_type=normalized,
|
|
raw=event_data,
|
|
payload=None,
|
|
input=None,
|
|
output=None,
|
|
known=False,
|
|
schema_version=None,
|
|
payload_mode=None,
|
|
validation_mode=None,
|
|
)
|
|
|
|
errors: list[str] = []
|
|
cache: dict[type[BaseModel], BaseModel | None] = {}
|
|
payload_snapshot = _model_snapshot(
|
|
contract.payload_model,
|
|
event_data,
|
|
"payload",
|
|
cache,
|
|
errors,
|
|
)
|
|
input_snapshot = _model_snapshot(
|
|
contract.input_model,
|
|
event_data,
|
|
"input",
|
|
cache,
|
|
errors,
|
|
)
|
|
output_snapshot = _model_snapshot(
|
|
contract.output_model,
|
|
event_data,
|
|
"output",
|
|
cache,
|
|
errors,
|
|
)
|
|
return EventPayloadSnapshot(
|
|
event_type=normalized,
|
|
raw=event_data,
|
|
payload=payload_snapshot,
|
|
input=input_snapshot,
|
|
output=output_snapshot,
|
|
known=True,
|
|
schema_version=contract.schema_version,
|
|
payload_mode=contract.payload_mode.value,
|
|
validation_mode=contract.validation_mode.value,
|
|
errors=tuple(errors),
|
|
)
|
|
|
|
|
|
__all__ = ["EventPayloadSnapshot", "snapshot_event_data"]
|