mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-01 21:47:50 +08:00
141 lines
5.2 KiB
Python
141 lines
5.2 KiB
Python
"""插件只读数据查询的持久化端口适配器。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Callable, Sequence
|
|
from typing import TypeVar
|
|
|
|
from pydantic import BaseModel
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.application.query import QueryRows
|
|
from app.db.oper.downloadhistory import DownloadHistoryOper
|
|
from app.db.oper.subscribe import SubscribeOper
|
|
from app.db.oper.subscribehistory import SubscribeHistoryOper
|
|
from app.db.oper.transferhistory import TransferHistoryOper
|
|
from app.schemas.query import (
|
|
DownloadHistoryFilter,
|
|
DownloadHistorySnapshot,
|
|
QueryPageRequest,
|
|
SubscriptionFilter,
|
|
SubscriptionHistoryFilter,
|
|
SubscriptionHistorySnapshot,
|
|
SubscriptionSnapshot,
|
|
TransferHistoryFilter,
|
|
TransferHistorySnapshot,
|
|
)
|
|
|
|
_SnapshotT = TypeVar("_SnapshotT", bound=BaseModel)
|
|
|
|
|
|
class SqlAlchemyDataQueryAdapter:
|
|
"""以短生命周期 Session 和显式 Oper 实现统一查询端口。
|
|
|
|
Oper 拥有表级筛选、排序和分页语义;适配器只管理一次操作使用的 Session,
|
|
并在 Session 关闭前把持久化记录冻结为稳定 Pydantic 快照。
|
|
"""
|
|
|
|
def __init__(self, session_factory: Callable[[], Session]) -> None:
|
|
"""保存由启动组合根提供的同步 Session 工厂。"""
|
|
self._session_factory = session_factory
|
|
|
|
@staticmethod
|
|
def _rows(
|
|
snapshot_type: type[_SnapshotT],
|
|
records: Sequence[object],
|
|
total: int,
|
|
) -> QueryRows[_SnapshotT]:
|
|
"""在会话有效期内投影一页记录,并保护非负总数合同。"""
|
|
return QueryRows(
|
|
items=[snapshot_type.model_validate(record) for record in records],
|
|
total=max(int(total), 0),
|
|
)
|
|
|
|
@staticmethod
|
|
def _item(
|
|
snapshot_type: type[_SnapshotT],
|
|
record: object | None,
|
|
) -> _SnapshotT | None:
|
|
"""把单条持久化记录投影为稳定快照。"""
|
|
return snapshot_type.model_validate(record) if record is not None else None
|
|
|
|
def list_subscriptions(
|
|
self,
|
|
*,
|
|
filters: SubscriptionFilter,
|
|
page: QueryPageRequest,
|
|
) -> QueryRows[SubscriptionSnapshot]:
|
|
"""通过订阅 Oper 读取并冻结一页当前订阅。"""
|
|
with self._session_factory() as session:
|
|
records, total = SubscribeOper(session).query(filters, page)
|
|
return self._rows(SubscriptionSnapshot, records, total)
|
|
|
|
def get_subscription(self, subscription_id: int) -> SubscriptionSnapshot | None:
|
|
"""通过订阅 Oper 按 ID 读取并冻结当前订阅。"""
|
|
with self._session_factory() as session:
|
|
record = SubscribeOper(session).get_by_id(subscription_id)
|
|
return self._item(SubscriptionSnapshot, record)
|
|
|
|
def list_subscription_history(
|
|
self,
|
|
*,
|
|
filters: SubscriptionHistoryFilter,
|
|
page: QueryPageRequest,
|
|
) -> QueryRows[SubscriptionHistorySnapshot]:
|
|
"""通过订阅历史 Oper 读取并冻结一页完成历史。"""
|
|
with self._session_factory() as session:
|
|
records, total = SubscribeHistoryOper(session).query(filters, page)
|
|
return self._rows(SubscriptionHistorySnapshot, records, total)
|
|
|
|
def get_subscription_history(
|
|
self,
|
|
history_id: int,
|
|
) -> SubscriptionHistorySnapshot | None:
|
|
"""通过订阅历史 Oper 按 ID 读取并冻结完成历史。"""
|
|
with self._session_factory() as session:
|
|
record = SubscribeHistoryOper(session).get_by_id(history_id)
|
|
return self._item(SubscriptionHistorySnapshot, record)
|
|
|
|
def list_download_history(
|
|
self,
|
|
*,
|
|
filters: DownloadHistoryFilter,
|
|
page: QueryPageRequest,
|
|
) -> QueryRows[DownloadHistorySnapshot]:
|
|
"""通过下载历史 Oper 读取并冻结一页下载记录。"""
|
|
with self._session_factory() as session:
|
|
records, total = DownloadHistoryOper(session).query(filters, page)
|
|
return self._rows(DownloadHistorySnapshot, records, total)
|
|
|
|
def get_download_history(
|
|
self,
|
|
history_id: int,
|
|
) -> DownloadHistorySnapshot | None:
|
|
"""通过下载历史 Oper 按 ID 读取并冻结下载记录。"""
|
|
with self._session_factory() as session:
|
|
record = DownloadHistoryOper(session).get_by_id(history_id)
|
|
return self._item(DownloadHistorySnapshot, record)
|
|
|
|
def list_transfer_history(
|
|
self,
|
|
*,
|
|
filters: TransferHistoryFilter,
|
|
page: QueryPageRequest,
|
|
) -> QueryRows[TransferHistorySnapshot]:
|
|
"""通过整理历史 Oper 读取并冻结一页整理记录。"""
|
|
with self._session_factory() as session:
|
|
records, total = TransferHistoryOper(session).query(filters, page)
|
|
return self._rows(TransferHistorySnapshot, records, total)
|
|
|
|
def get_transfer_history(
|
|
self,
|
|
history_id: int,
|
|
) -> TransferHistorySnapshot | None:
|
|
"""通过整理历史 Oper 按 ID 读取并冻结整理记录。"""
|
|
with self._session_factory() as session:
|
|
record = TransferHistoryOper(session).get_by_id(history_id)
|
|
return self._item(TransferHistorySnapshot, record)
|
|
|
|
|
|
__all__ = ["SqlAlchemyDataQueryAdapter"]
|