mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-05 23:47:41 +08:00
refactor: unify durable event topics
This commit is contained in:
@@ -2,15 +2,43 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from collections.abc import Callable, Mapping
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from types import MappingProxyType
|
||||
from typing import Any, Protocol, TypeVar
|
||||
|
||||
from app.schemas.types import EventType
|
||||
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
SUBSCRIBE_ADDED_TOPIC = "subscribe.added"
|
||||
SUBSCRIBE_MODIFIED_TOPIC = "subscribe.modified"
|
||||
SUBSCRIBE_DELETED_TOPIC = "subscribe.deleted"
|
||||
DOWNLOAD_ADDED_TOPIC = "download.added"
|
||||
TRANSFER_COMPLETED_TOPIC = "transfer.completed"
|
||||
TRANSFER_FAILED_TOPIC = "transfer.failed"
|
||||
|
||||
DURABLE_EVENT_TOPICS: Mapping[EventType, str] = MappingProxyType({
|
||||
EventType.SubscribeAdded: SUBSCRIBE_ADDED_TOPIC,
|
||||
EventType.SubscribeModified: SUBSCRIBE_MODIFIED_TOPIC,
|
||||
EventType.SubscribeDeleted: SUBSCRIBE_DELETED_TOPIC,
|
||||
EventType.DownloadAdded: DOWNLOAD_ADDED_TOPIC,
|
||||
EventType.TransferComplete: TRANSFER_COMPLETED_TOPIC,
|
||||
EventType.TransferFailed: TRANSFER_FAILED_TOPIC,
|
||||
})
|
||||
|
||||
|
||||
def durable_event_topic(event_type: EventType) -> str:
|
||||
"""返回 durable-required 事件唯一登记的 outbox topic。"""
|
||||
try:
|
||||
return DURABLE_EVENT_TOPICS[event_type]
|
||||
except KeyError as error:
|
||||
raise ValueError(f"事件 {event_type.name} 未登记 durable topic") from error
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class OutboxIntent:
|
||||
"""与业务事务一起暂存的版本化副作用意图。"""
|
||||
@@ -33,6 +61,18 @@ class ClaimedOutboxMessage:
|
||||
attempt: int
|
||||
|
||||
|
||||
def validate_durable_event_handlers(
|
||||
handlers: Mapping[str, Callable[[ClaimedOutboxMessage], None]],
|
||||
) -> None:
|
||||
"""拒绝缺少任一 durable-required 事件恢复 handler 的 dispatcher。"""
|
||||
missing = set(DURABLE_EVENT_TOPICS.values()) - set(handlers)
|
||||
if missing:
|
||||
raise RuntimeError(
|
||||
"Outbox dispatcher 缺少 durable 事件 handler: "
|
||||
+ ", ".join(sorted(missing))
|
||||
)
|
||||
|
||||
|
||||
class OutboxRepository(Protocol):
|
||||
"""outbox 写入、claim 和终态更新所需的最小端口。"""
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ from app.application.outbox import (
|
||||
OutboxIntent,
|
||||
SyncOutboxTransaction,
|
||||
SyncUnitOfWork,
|
||||
SUBSCRIBE_DELETED_TOPIC,
|
||||
)
|
||||
from app.schemas.event import SubscribeDeletedEventData
|
||||
|
||||
@@ -251,7 +252,7 @@ def _build_deletion_effects(
|
||||
report_payload=report_payload,
|
||||
event_intent=OutboxIntent(
|
||||
event_key=event_key,
|
||||
topic="subscribe.deleted",
|
||||
topic=SUBSCRIBE_DELETED_TOPIC,
|
||||
payload=event_payload,
|
||||
),
|
||||
report_intent=OutboxIntent(
|
||||
|
||||
@@ -3,7 +3,11 @@
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any, Callable, Protocol
|
||||
|
||||
from app.application.outbox import AsyncOutboxTransaction, OutboxIntent
|
||||
from app.application.outbox import (
|
||||
AsyncOutboxTransaction,
|
||||
OutboxIntent,
|
||||
SUBSCRIBE_DELETED_TOPIC,
|
||||
)
|
||||
from app.application.subscription.delete import (
|
||||
AsyncUnitOfWork,
|
||||
SubscribeDeletedPublisher,
|
||||
@@ -89,7 +93,7 @@ class DeleteSubscriptionsByIdentityCommand:
|
||||
await self._outbox.stage(
|
||||
OutboxIntent(
|
||||
event_key=event_payload["idempotency_key"],
|
||||
topic="subscribe.deleted",
|
||||
topic=SUBSCRIBE_DELETED_TOPIC,
|
||||
payload=event_payload,
|
||||
),
|
||||
now,
|
||||
|
||||
@@ -7,7 +7,11 @@ from datetime import datetime, timezone
|
||||
from typing import Any, Protocol
|
||||
from uuid import uuid4
|
||||
|
||||
from app.application.outbox import AsyncOutboxTransaction, OutboxIntent
|
||||
from app.application.outbox import (
|
||||
AsyncOutboxTransaction,
|
||||
OutboxIntent,
|
||||
SUBSCRIBE_MODIFIED_TOPIC,
|
||||
)
|
||||
from app.schemas.event import SubscribeModifiedEventData
|
||||
|
||||
|
||||
@@ -143,7 +147,7 @@ class SubscriptionMutationService:
|
||||
await self._outbox.stage(
|
||||
OutboxIntent(
|
||||
event_key=event_key,
|
||||
topic="subscribe.modified",
|
||||
topic=SUBSCRIBE_MODIFIED_TOPIC,
|
||||
payload=event_payload,
|
||||
),
|
||||
datetime.now(timezone.utc),
|
||||
|
||||
@@ -19,7 +19,7 @@ from collections.abc import Awaitable, Callable
|
||||
from datetime import datetime, timezone
|
||||
from typing import Mapping, Optional, Protocol, Tuple
|
||||
|
||||
from app.application.outbox import OutboxIntent
|
||||
from app.application.outbox import OutboxIntent, SUBSCRIBE_ADDED_TOPIC
|
||||
from app.domain.context import MediaInfo, MusicInfo
|
||||
from app.schemas.media import resolve_media_identity
|
||||
from app.schemas.types import MUSIC_ENTITY_ALBUM, MediaType
|
||||
@@ -243,7 +243,7 @@ def _subscribe_added_intents(
|
||||
intents: list[OutboxIntent] = [
|
||||
OutboxIntent(
|
||||
event_key=event_key,
|
||||
topic="subscribe.added",
|
||||
topic=SUBSCRIBE_ADDED_TOPIC,
|
||||
payload=event_payload,
|
||||
),
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user