mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-05 23:47:41 +08:00
refactor: 推进后端分层架构治理
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
"""按媒体身份批量删除订阅的应用用例。"""
|
||||
|
||||
from typing import Callable, Protocol
|
||||
|
||||
from app.application.subscription.delete import (
|
||||
AsyncUnitOfWork,
|
||||
SubscribeDeletedPublisher,
|
||||
SubscribeDeletionActor,
|
||||
SubscribeDeletionCandidate,
|
||||
)
|
||||
from app.schemas.types import MediaSource
|
||||
|
||||
|
||||
class SubscribeIdentityDeletionRepository(Protocol):
|
||||
"""按媒体身份删除订阅所需的数据访问端口。"""
|
||||
|
||||
async def list_candidates_by_identity(
|
||||
self,
|
||||
media_source: MediaSource,
|
||||
media_id: str,
|
||||
season: int | None,
|
||||
music_type: str | None,
|
||||
) -> list[SubscribeDeletionCandidate]:
|
||||
"""读取匹配媒体身份的去重订阅快照。"""
|
||||
...
|
||||
|
||||
async def delete(self, subscribe_id: int) -> None:
|
||||
"""把指定订阅登记为待删除。"""
|
||||
...
|
||||
|
||||
|
||||
SubscribeDeletionEventErrorHandler = Callable[[int, Exception], None]
|
||||
|
||||
|
||||
class DeleteSubscriptionsByIdentityCommand:
|
||||
"""按媒体身份删除当前用户可访问的全部订阅。"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
repository: SubscribeIdentityDeletionRepository,
|
||||
unit_of_work: AsyncUnitOfWork,
|
||||
publish_deleted: SubscribeDeletedPublisher,
|
||||
handle_event_error: SubscribeDeletionEventErrorHandler,
|
||||
) -> None:
|
||||
"""注入数据访问、事务、事件和事件错误处理端口。"""
|
||||
self._repository = repository
|
||||
self._unit_of_work = unit_of_work
|
||||
self._publish_deleted = publish_deleted
|
||||
self._handle_event_error = handle_event_error
|
||||
|
||||
async def execute(
|
||||
self,
|
||||
media_source: MediaSource,
|
||||
media_id: str,
|
||||
season: int | None,
|
||||
music_type: str | None,
|
||||
actor: SubscribeDeletionActor,
|
||||
) -> int:
|
||||
"""删除匹配订阅,并在提交后逐条发送兼容事件。"""
|
||||
candidates = await self._repository.list_candidates_by_identity(
|
||||
media_source,
|
||||
media_id,
|
||||
season,
|
||||
music_type,
|
||||
)
|
||||
deletions = [
|
||||
candidate
|
||||
for candidate in candidates
|
||||
if self._can_delete(candidate, actor)
|
||||
]
|
||||
for candidate in deletions:
|
||||
await self._repository.stage_delete(candidate.subscribe_id)
|
||||
|
||||
try:
|
||||
await self._unit_of_work.commit()
|
||||
except Exception:
|
||||
await self._unit_of_work.rollback()
|
||||
raise
|
||||
|
||||
for candidate in deletions:
|
||||
try:
|
||||
await self._publish_deleted(
|
||||
candidate.subscribe_id,
|
||||
dict(candidate.event_payload),
|
||||
)
|
||||
except Exception as error:
|
||||
self._handle_event_error(candidate.subscribe_id, error)
|
||||
return len(deletions)
|
||||
|
||||
@staticmethod
|
||||
def _can_delete(
|
||||
candidate: SubscribeDeletionCandidate,
|
||||
actor: SubscribeDeletionActor,
|
||||
) -> bool:
|
||||
"""判断用户是否拥有候选订阅的删除权限。"""
|
||||
if actor.is_superuser:
|
||||
return True
|
||||
return bool(candidate.username) and candidate.username == actor.username
|
||||
Reference in New Issue
Block a user