refactor: isolate transfer and download history queries

This commit is contained in:
jxxghp
2026-08-23 13:59:12 +08:00
parent 03c03fa27d
commit 4074fa4e42
10 changed files with 505 additions and 348 deletions
+78
View File
@@ -16,6 +16,8 @@
SQLAlchemy 归还连接时已在池层吞掉异常并 invalidate 坏连接,再把释放故障升级成调用方
的异常,只会让一次已经落库的写入看起来像失败,诱发重复提交。
"""
from functools import wraps
from inspect import Parameter, signature
from typing import Any, Awaitable, Callable, Optional, TypeVar
from sqlalchemy.ext.asyncio import AsyncSession
@@ -296,3 +298,79 @@ def async_db_query(func: Callable[..., Awaitable[_R]]) -> Callable[..., Awaitabl
return result
return wrapper
def legacy_db_query(func: Callable[..., _R]) -> Callable[..., _R]:
"""保留旧 Model 查询 ABI,同时让新调用方复用显式 Session。
旧插件通常省略 ``db``,直接把业务参数放在第一个位置;通用 ``db_query``
装饰器只适用于固定的 ``(db, ...)`` 形状,不能把这类位置参数直接套进去。
这里按签名插入会话,避免丢失旧插件传入的第一个业务参数。
"""
@wraps(func)
def wrapper(*args: Any, **kwargs: Any) -> _R:
db = _get_args_db(args, kwargs)
if db is not None:
return func(*args, **kwargs)
session = ScopedSession()
call_args, call_kwargs = _inject_legacy_db(func, args, kwargs, session)
try:
return func(*call_args, **call_kwargs)
finally:
try:
session.close()
except Exception as close_err: # noqa: BLE001 释放故障不得改变旧 ABI 返回值
logger.error(f"释放数据库会话失败:{close_err}")
return wrapper
def legacy_async_db_query(
func: Callable[..., Awaitable[_R]],
) -> Callable[..., Awaitable[_R]]:
"""保留旧 Model 异步查询 ABI,同时让新调用方复用显式 AsyncSession。"""
@wraps(func)
async def wrapper(*args: Any, **kwargs: Any) -> _R:
db = _get_args_async_db(args, kwargs)
if db is not None:
return await func(*args, **kwargs)
async with async_session_scope() as session:
call_args, call_kwargs = _inject_legacy_db(func, args, kwargs, session)
return await func(*call_args, **call_kwargs)
return wrapper
def _inject_legacy_db(
func: Callable[..., _R],
args: tuple[Any, ...],
kwargs: dict[str, Any],
db: Any,
) -> tuple[tuple[Any, ...], dict[str, Any]]:
"""按旧 Model 方法签名注入兼容会话,不吞掉位置业务参数。"""
call_args = list(args)
call_kwargs = dict(kwargs)
parameters = list(signature(func).parameters.values())
db_index = next(
(index for index, parameter in enumerate(parameters) if parameter.name == "db"),
None,
)
if "db" in call_kwargs:
call_kwargs["db"] = db
return tuple(call_args), call_kwargs
if db_index is None:
# 兼容没有显式 db 参数的极旧函数,保持调用失败方式与普通 Python 一致。
return tuple(call_args), {"db": db, **call_kwargs}
if db_index < len(call_args) and call_args[db_index] is None:
call_args[db_index] = db
elif db_index < len(parameters) and parameters[db_index].kind is Parameter.POSITIONAL_ONLY:
call_args.insert(db_index, db)
elif db_index <= len(call_args):
call_args.insert(db_index, db)
else:
call_kwargs["db"] = db
return tuple(call_args), call_kwargs
+17 -17
View File
@@ -6,7 +6,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import Mapped, Session, mapped_column
from app.db.base import Base, execute_dml, get_id_column
from app.db.decorators import async_db_query, db_query
from app.db.decorators import legacy_async_db_query, legacy_db_query
from app.db.models._constraints import media_identity_constraint
from app.schemas.types import MediaSource
@@ -77,7 +77,7 @@ class DownloadHistory(Base):
)
@classmethod
@db_query
@legacy_db_query
def get_by_hash(cls, db: Session, download_hash: str):
return db.execute(
select(DownloadHistory)
@@ -86,7 +86,7 @@ class DownloadHistory(Base):
).scalars().first()
@classmethod
@db_query
@legacy_db_query
def get_by_hashes(cls, db: Session, download_hashes: List[str]):
"""
批量查询多个下载任务的最新历史记录,避免在上层形成 N+1 查询。
@@ -119,7 +119,7 @@ class DownloadHistory(Base):
]
@classmethod
@db_query
@legacy_db_query
def get_by_media_identity(
cls, db: Session, media_source: MediaSource, media_id: str,
music_type: Optional[str] = None,
@@ -136,7 +136,7 @@ class DownloadHistory(Base):
return list(db.execute(statement).scalars().all())
@classmethod
@db_query
@legacy_db_query
def list_by_page(
cls, db: Session, page: int = 1, count: int = 30
):
@@ -148,7 +148,7 @@ class DownloadHistory(Base):
).scalars().all())
@classmethod
@async_db_query
@legacy_async_db_query
async def async_list_by_page(
cls, db: AsyncSession, page: int = 1, count: int = 30
):
@@ -161,7 +161,7 @@ class DownloadHistory(Base):
return list(result.scalars().all())
@classmethod
@async_db_query
@legacy_async_db_query
async def async_list_by_title(
cls,
db: AsyncSession,
@@ -177,13 +177,13 @@ class DownloadHistory(Base):
return list(result.scalars().all())
@classmethod
@async_db_query
@legacy_async_db_query
async def async_count(cls, db: AsyncSession):
result = await db.execute(select(func.count(cls.id)))
return result.scalar()
@classmethod
@async_db_query
@legacy_async_db_query
async def async_count_by_title(cls, db: AsyncSession, title: str):
result = await db.execute(
select(func.count(cls.id)).filter(_title_like(cls.title, title))
@@ -191,14 +191,14 @@ class DownloadHistory(Base):
return result.scalar()
@classmethod
@db_query
@legacy_db_query
def get_by_path(cls, db: Session, path: str):
return db.execute(
select(DownloadHistory).where(DownloadHistory.path == path)
).scalars().first()
@classmethod
@db_query
@legacy_db_query
def get_last_by(
cls,
db: Session,
@@ -237,7 +237,7 @@ class DownloadHistory(Base):
@classmethod
@db_query
@legacy_db_query
def list_by_user_date(cls, db: Session, date: str, username: Optional[str] = None):
"""
查询某用户某时间之前的下载历史。
@@ -256,7 +256,7 @@ class DownloadHistory(Base):
).scalars().all())
@classmethod
@db_query
@legacy_db_query
def list_by_date(
cls,
db: Session,
@@ -282,7 +282,7 @@ class DownloadHistory(Base):
).scalars().all())
@classmethod
@db_query
@legacy_db_query
def list_by_type(cls, db: Session, mtype: str, days: int):
return list(db.execute(
select(DownloadHistory).where(
@@ -345,7 +345,7 @@ class DownloadFiles(Base):
)
@classmethod
@db_query
@legacy_db_query
def get_by_hash(cls, db: Session, download_hash: str, state: Optional[int] = None):
statement = select(cls).where(cls.download_hash == download_hash)
if state is not None:
@@ -353,7 +353,7 @@ class DownloadFiles(Base):
return list(db.execute(statement).scalars().all())
@classmethod
@db_query
@legacy_db_query
def get_by_fullpath(cls, db: Session, fullpath: str, all_files: bool = False):
result = db.execute(
select(cls).where(cls.fullpath == fullpath).order_by(cls.id.desc())
@@ -361,7 +361,7 @@ class DownloadFiles(Base):
return list(result.all()) if all_files else result.first()
@classmethod
@db_query
@legacy_db_query
def get_by_savepath(cls, db: Session, savepath: str):
return list(db.execute(select(cls).where(cls.savepath == savepath)).scalars().all())
+91 -47
View File
@@ -8,7 +8,11 @@ from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import Mapped, Session, mapped_column
from app.db.base import Base, execute_dml, get_id_column
from app.db.decorators import async_db_query, db_query
from app.db.decorators import (
legacy_async_db_query,
legacy_db_query,
run_legacy_sync_query,
)
from app.db.models._constraints import media_identity_constraint
from app.schemas.types import MUSIC_ENTITY_ALBUM, MUSIC_ENTITY_RECORDING, MediaSource, MediaType
@@ -94,7 +98,7 @@ class TransferHistory(Base):
)
@classmethod
@db_query
@legacy_db_query
def list_by_title(cls, db: Session, title: str, page: int = 1, count: int = 30,
status: Optional[bool] = None, wildcard: bool = False):
if wildcard:
@@ -121,7 +125,7 @@ class TransferHistory(Base):
return list(db.execute(statement).scalars().all())
@classmethod
@async_db_query
@legacy_async_db_query
async def async_list_by_title(cls, db: AsyncSession, title: str, page: int = 1, count: int = 30,
status: Optional[bool] = None, wildcard: bool = False):
if wildcard:
@@ -149,7 +153,7 @@ class TransferHistory(Base):
return list(result.scalars().all())
@classmethod
@db_query
@legacy_db_query
def list_by_page(cls, db: Session, page: int = 1, count: int = 30, status: Optional[bool] = None):
statement = select(cls)
if status is not None:
@@ -163,7 +167,7 @@ class TransferHistory(Base):
return list(db.execute(statement).scalars().all())
@classmethod
@async_db_query
@legacy_async_db_query
async def async_list_by_page(cls, db: AsyncSession, page: int = 1, count: int = 30,
status: Optional[bool] = None):
if status is not None:
@@ -185,16 +189,29 @@ class TransferHistory(Base):
return list(result.scalars().all())
@classmethod
@db_query
def get_by_hash(cls, db: Session, download_hash: str):
return db.execute(
select(cls).where(cls.download_hash == download_hash)
).scalars().first()
def get_by_hash(
cls,
db: Session | str | None = None,
download_hash: str | None = None,
):
"""按下载哈希查询最新记录,兼容旧插件无会话调用。"""
if download_hash is None and isinstance(db, str):
download_hash, db = db, None
if download_hash is None:
raise TypeError("download_hash is required")
def query(session: Session):
"""在调用方提供的同步会话中执行哈希查询。"""
return session.execute(
select(cls).where(cls.download_hash == download_hash)
).scalars().first()
return query(db) if isinstance(db, Session) else run_legacy_sync_query(query)
@classmethod
@db_query
def get_by_src(
cls, db: Session, src: str, storage: Optional[str] = None
cls, db: Session | str | None = None, src: str | None = None,
storage: Optional[str] = None
) -> Optional["TransferHistory"]:
"""
按源路径和存储查询单条整理记录。
@@ -204,17 +221,26 @@ class TransferHistory(Base):
:param storage: 源存储类型
:return: 命中的整理记录,未命中时返回 None
"""
statement = select(cls).where(cls.src == src)
if storage:
statement = statement.where(cls.src_storage == storage)
return db.execute(
statement.order_by(cls.id.desc())
).scalars().first()
if src is None and isinstance(db, str):
src, db = db, None
if src is None:
raise TypeError("src is required")
def query(session: Session):
"""在调用方提供的同步会话中执行源路径查询。"""
statement = select(cls).where(cls.src == src)
if storage:
statement = statement.where(cls.src_storage == storage)
return session.execute(
statement.order_by(cls.id.desc())
).scalars().first()
return query(db) if isinstance(db, Session) else run_legacy_sync_query(query)
@classmethod
@db_query
def get_success_by_src(
cls, db: Session, src: str, storage: Optional[str] = None
cls, db: Session | str | None = None, src: str | None = None,
storage: Optional[str] = None
) -> Optional["TransferHistory"]:
"""
按源路径和存储查询成功的整理记录,源路径原样精确匹配。
@@ -226,17 +252,26 @@ class TransferHistory(Base):
:param storage: 源存储类型
:return: 命中的成功整理记录,未命中时返回 None
"""
statement = select(cls).where(cls.src == src, cls.status.is_(True))
if storage:
statement = statement.where(cls.src_storage == storage)
return db.execute(
statement.order_by(cls.id.desc())
).scalars().first()
if src is None and isinstance(db, str):
src, db = db, None
if src is None:
raise TypeError("src is required")
def query(session: Session):
"""在调用方提供的同步会话中执行成功源路径查询。"""
statement = select(cls).where(cls.src == src, cls.status.is_(True))
if storage:
statement = statement.where(cls.src_storage == storage)
return session.execute(
statement.order_by(cls.id.desc())
).scalars().first()
return query(db) if isinstance(db, Session) else run_legacy_sync_query(query)
@classmethod
@db_query
def get_by_dest(
cls, db: Session, dest: str, storage: Optional[str] = None
cls, db: Session | str | None = None, dest: str | None = None,
storage: Optional[str] = None
) -> Optional["TransferHistory"]:
"""
按目标路径和存储查询单条整理记录。
@@ -246,15 +281,24 @@ class TransferHistory(Base):
:param storage: 目标存储类型
:return: 命中的整理记录,未命中时返回 None
"""
statement = select(cls).where(cls.dest == dest)
if storage:
statement = statement.where(cls.dest_storage == storage)
return db.execute(
statement.order_by(cls.id.desc())
).scalars().first()
if dest is None and isinstance(db, str):
dest, db = db, None
if dest is None:
raise TypeError("dest is required")
def query(session: Session):
"""在调用方提供的同步会话中执行目标路径查询。"""
statement = select(cls).where(cls.dest == dest)
if storage:
statement = statement.where(cls.dest_storage == storage)
return session.execute(
statement.order_by(cls.id.desc())
).scalars().first()
return query(db) if isinstance(db, Session) else run_legacy_sync_query(query)
@classmethod
@db_query
@legacy_db_query
def list_success_by_src(
cls,
db: Session,
@@ -294,7 +338,7 @@ class TransferHistory(Base):
return list(db.execute(statement).scalars().all())
@classmethod
@db_query
@legacy_db_query
def list_success_move_by_dest(
cls,
db: Session,
@@ -337,14 +381,14 @@ class TransferHistory(Base):
return list(db.execute(statement).scalars().all())
@classmethod
@db_query
@legacy_db_query
def list_by_hash(cls, db: Session, download_hash: str):
return list(db.execute(
select(cls).where(cls.download_hash == download_hash)
).scalars().all())
@classmethod
@db_query
@legacy_db_query
def statistic(cls, db: Session, days: int = 7):
"""
统计最近days天的下载历史数量,按日期分组返回每日数量
@@ -361,7 +405,7 @@ class TransferHistory(Base):
).all())
@classmethod
@db_query
@legacy_db_query
def monthly_media_statistics(cls, db: Session):
"""
统计当月成功整理的电影、电视剧、剧集和音乐数量。
@@ -427,7 +471,7 @@ class TransferHistory(Base):
return 1
@classmethod
@async_db_query
@legacy_async_db_query
async def async_statistic(cls, db: AsyncSession, days: int = 7):
"""
统计最近days天的下载历史数量,按日期分组返回每日数量
@@ -442,7 +486,7 @@ class TransferHistory(Base):
return result.all()
@classmethod
@db_query
@legacy_db_query
def count(cls, db: Session, status: Optional[bool] = None):
statement = select(func.count(cls.id))
if status is not None:
@@ -450,7 +494,7 @@ class TransferHistory(Base):
return db.execute(statement).scalar()
@classmethod
@async_db_query
@legacy_async_db_query
async def async_count(cls, db: AsyncSession, status: Optional[bool] = None):
if status is not None:
result = await db.execute(
@@ -463,7 +507,7 @@ class TransferHistory(Base):
return result.scalar()
@classmethod
@db_query
@legacy_db_query
def count_by_title(cls, db: Session, title: str, status: Optional[bool] = None, wildcard: bool = False):
if wildcard:
text_filter = or_(
@@ -483,7 +527,7 @@ class TransferHistory(Base):
return db.execute(statement).scalar()
@classmethod
@async_db_query
@legacy_async_db_query
async def async_count_by_title(cls, db: AsyncSession, title: str, status: Optional[bool] = None, wildcard: bool = False):
if wildcard:
text_filter = or_(
@@ -504,7 +548,7 @@ class TransferHistory(Base):
return result.scalar()
@classmethod
@db_query
@legacy_db_query
def list_by(cls, db: Session, mtype: Optional[str] = None, title: Optional[str] = None, year: Optional[str] = None,
season: Optional[str] = None,
episode: Optional[str] = None,
@@ -542,7 +586,7 @@ class TransferHistory(Base):
return list(db.execute(statement).scalars().all())
@classmethod
@db_query
@legacy_db_query
def get_by_media_identity(
cls, db: Session, media_source: MediaSource, media_id: str,
mtype: Optional[str] = None,
@@ -589,7 +633,7 @@ class TransferHistory(Base):
return history
@classmethod
@db_query
@legacy_db_query
def list_by_date(cls, db: Session, date: str):
"""
查询某时间之后的转移历史
+94 -38
View File
@@ -18,20 +18,28 @@ class DownloadHistoryOper(DbOper):
按路径查询下载记录
:param path: 数据key
"""
return DownloadHistory.get_by_path(self._db, path)
return self._execute_sync_query(
lambda session: DownloadHistory.get_by_path(session, path)
)
def get_by_hash(self, download_hash: str) -> Optional[DownloadHistory]:
"""
按Hash查询下载记录
:param download_hash: 数据key
"""
return DownloadHistory.get_by_hash(self._db, download_hash)
return self._execute_sync_query(
lambda session: DownloadHistory.get_by_hash(session, download_hash)
)
def get_by_hashes(self, download_hashes: List[str]) -> Dict[str, DownloadHistory]:
"""
批量按 Hash 查询下载记录,并返回以 Hash 为键的映射。
"""
histories = DownloadHistory.get_by_hashes(self._db, download_hashes)
histories = self._execute_sync_query(
lambda session: DownloadHistory.get_by_hashes(
session, download_hashes
)
)
return {
history.download_hash: history
for history in histories
@@ -48,11 +56,13 @@ class DownloadHistoryOper(DbOper):
:param media_id: 数据源原生 ID
:param music_type: 音乐实体类型
"""
return DownloadHistory.get_by_media_identity(
self._db,
media_source=media_source,
media_id=media_id,
music_type=music_type,
return self._execute_sync_query(
lambda session: DownloadHistory.get_by_media_identity(
session,
media_source=media_source,
media_id=media_id,
music_type=music_type,
)
)
def add(self, **kwargs):
@@ -97,30 +107,48 @@ class DownloadHistoryOper(DbOper):
:param download_hash: 数据key
:param state: 删除状态
"""
return DownloadFiles.get_by_hash(self._db, download_hash, state)
return self._execute_sync_query(
lambda session: DownloadFiles.get_by_hash(
session, download_hash, state
)
)
def get_file_by_fullpath(self, fullpath: str) -> Optional[DownloadFiles]:
"""
按fullpath查询下载文件记录
:param fullpath: 数据key
"""
return cast(Optional[DownloadFiles],
DownloadFiles.get_by_fullpath(self._db, fullpath=fullpath, all_files=False))
return self._execute_sync_query(
lambda session: cast(
Optional[DownloadFiles],
DownloadFiles.get_by_fullpath(
session, fullpath=fullpath, all_files=False
),
)
)
def get_files_by_fullpath(self, fullpath: str) -> List[DownloadFiles]:
"""
按fullpath查询下载文件记录
:param fullpath: 数据key
"""
return cast(List[DownloadFiles],
DownloadFiles.get_by_fullpath(self._db, fullpath=fullpath, all_files=True))
return self._execute_sync_query(
lambda session: cast(
List[DownloadFiles],
DownloadFiles.get_by_fullpath(
session, fullpath=fullpath, all_files=True
),
)
)
def get_files_by_savepath(self, fullpath: str) -> List[DownloadFiles]:
"""
按savepath查询下载文件记录
:param fullpath: 数据key
"""
return DownloadFiles.get_by_savepath(self._db, fullpath)
return self._execute_sync_query(
lambda session: DownloadFiles.get_by_savepath(session, fullpath)
)
def delete_file_by_fullpath(self, fullpath: str):
"""
@@ -147,8 +175,14 @@ class DownloadHistoryOper(DbOper):
按fullpath查询下载文件记录hash
:param fullpath: 数据key
"""
fileinfo = cast(Optional[DownloadFiles],
DownloadFiles.get_by_fullpath(self._db, fullpath=fullpath, all_files=False))
fileinfo = self._execute_sync_query(
lambda session: cast(
Optional[DownloadFiles],
DownloadFiles.get_by_fullpath(
session, fullpath=fullpath, all_files=False
),
)
)
if fileinfo:
return fileinfo.download_hash
return ""
@@ -157,7 +191,9 @@ class DownloadHistoryOper(DbOper):
"""
分页查询下载历史
"""
return DownloadHistory.list_by_page(self._db, page, count)
return self._execute_sync_query(
lambda session: DownloadHistory.list_by_page(session, page, count)
)
async def async_list_by_page(
self,
@@ -165,7 +201,11 @@ class DownloadHistoryOper(DbOper):
count: int = 30,
) -> List[DownloadHistory]:
"""异步分页查询下载历史。"""
return await DownloadHistory.async_list_by_page(self._db, page, count)
return await self._execute_async_query(
lambda session: DownloadHistory.async_list_by_page(
session, page, count
)
)
async def async_delete_history(self, historyid: int):
"""
@@ -187,22 +227,30 @@ class DownloadHistoryOper(DbOper):
按类型、标题、年份、季集查询下载记录
媒体身份 + mtype 或 title + year
"""
return DownloadHistory.get_last_by(db=self._db,
mtype=mtype,
title=title,
year=year,
season=season,
episode=episode,
media_source=media_source,
media_id=media_id)
return self._execute_sync_query(
lambda session: DownloadHistory.get_last_by(
db=session,
mtype=mtype,
title=title,
year=year,
season=season,
episode=episode,
media_source=media_source,
media_id=media_id,
)
)
def list_by_user_date(self, date: str, username: Optional[str] = None) -> List[DownloadHistory]:
"""
查询某用户某时间之前的下载历史
"""
return DownloadHistory.list_by_user_date(db=self._db,
date=date,
username=username)
return self._execute_sync_query(
lambda session: DownloadHistory.list_by_user_date(
db=session,
date=date,
username=username,
)
)
def list_by_date(
self, date: str, type: str, media_source: MediaSource, media_id: str,
@@ -211,20 +259,28 @@ class DownloadHistoryOper(DbOper):
"""
查询某时间之后的下载历史
"""
return DownloadHistory.list_by_date(db=self._db,
date=date,
type=type,
media_source=media_source,
media_id=media_id,
seasons=seasons)
return self._execute_sync_query(
lambda session: DownloadHistory.list_by_date(
db=session,
date=date,
type=type,
media_source=media_source,
media_id=media_id,
seasons=seasons,
)
)
def list_by_type(self, mtype: str, days: int = 7) -> List[DownloadHistory]:
"""
获取指定类型的下载历史
"""
return DownloadHistory.list_by_type(db=self._db,
mtype=mtype,
days=days)
return self._execute_sync_query(
lambda session: DownloadHistory.list_by_type(
db=session,
mtype=mtype,
days=days,
)
)
def delete_history(self, historyid):
"""
+92 -50
View File
@@ -19,13 +19,17 @@ class TransferHistoryOper(DbOper):
获取转移历史
:param historyid: 转移历史id
"""
return TransferHistory.get(self._db, historyid)
return self._execute_sync_query(
lambda session: TransferHistory.get(session, historyid)
)
async def async_get(self, historyid: int) -> Optional[TransferHistory]:
"""
异步获取转移历史。
"""
return await TransferHistory.async_get(self._db, historyid)
return await self._execute_async_query(
lambda session: TransferHistory.async_get(session, historyid)
)
async def async_list_by_title(
self,
@@ -38,13 +42,15 @@ class TransferHistoryOper(DbOper):
"""
异步按标题分页查询转移记录。
"""
return await TransferHistory.async_list_by_title(
self._db,
title=title,
page=page,
count=count,
status=status,
wildcard=wildcard,
return await self._execute_async_query(
lambda session: TransferHistory.async_list_by_title(
session,
title=title,
page=page,
count=count,
status=status,
wildcard=wildcard,
)
)
async def async_list_by_page(
@@ -56,15 +62,19 @@ class TransferHistoryOper(DbOper):
"""
异步分页查询转移记录。
"""
return await TransferHistory.async_list_by_page(
self._db, page=page, count=count, status=status
return await self._execute_async_query(
lambda session: TransferHistory.async_list_by_page(
session, page=page, count=count, status=status
)
)
async def async_count(self, status: Optional[bool] = None) -> Optional[int]:
"""
异步统计转移记录数量。
"""
return await TransferHistory.async_count(self._db, status=status)
return await self._execute_async_query(
lambda session: TransferHistory.async_count(session, status=status)
)
async def async_count_by_title(
self,
@@ -75,11 +85,13 @@ class TransferHistoryOper(DbOper):
"""
异步按标题统计转移记录数量。
"""
return await TransferHistory.async_count_by_title(
self._db,
title=title,
status=status,
wildcard=wildcard,
return await self._execute_async_query(
lambda session: TransferHistory.async_count_by_title(
session,
title=title,
status=status,
wildcard=wildcard,
)
)
def get_by_title(self, title: str) -> List[TransferHistory]:
@@ -87,7 +99,9 @@ class TransferHistoryOper(DbOper):
按标题查询转移记录
:param title: 数据key
"""
return TransferHistory.list_by_title(self._db, title)
return self._execute_sync_query(
lambda session: TransferHistory.list_by_title(session, title)
)
def get_by_src(
self, src: str, storage: Optional[str] = None
@@ -98,7 +112,9 @@ class TransferHistoryOper(DbOper):
:param storage: 存储类型
:return: 命中的整理记录,未命中时返回 None
"""
return TransferHistory.get_by_src(self._db, src, storage)
return self._execute_sync_query(
lambda session: TransferHistory.get_by_src(session, src, storage)
)
def get_success_by_src(
self, src: str, storage: Optional[str] = None
@@ -109,7 +125,11 @@ class TransferHistoryOper(DbOper):
:param storage: 存储类型
:return: 命中的成功整理记录,未命中时返回 None
"""
return TransferHistory.get_success_by_src(self._db, src, storage)
return self._execute_sync_query(
lambda session: TransferHistory.get_success_by_src(
session, src, storage
)
)
def get_by_dest(
self, dest: str, storage: Optional[str] = None
@@ -119,7 +139,9 @@ class TransferHistoryOper(DbOper):
:param dest: 数据key
:param storage: 存储类型
"""
return TransferHistory.get_by_dest(self._db, dest, storage)
return self._execute_sync_query(
lambda session: TransferHistory.get_by_dest(session, dest, storage)
)
def list_success_by_src(
self,
@@ -135,11 +157,13 @@ class TransferHistoryOper(DbOper):
:param recursive: 是否递归匹配目录子项
:return: 命中的成功整理记录
"""
return TransferHistory.list_success_by_src(
self._db,
src=src,
storage=storage,
recursive=recursive,
return self._execute_sync_query(
lambda session: TransferHistory.list_success_by_src(
session,
src=src,
storage=storage,
recursive=recursive,
)
)
def list_success_move_by_dest(
@@ -156,11 +180,13 @@ class TransferHistoryOper(DbOper):
:param recursive: 是否递归匹配目录子项
:return: 命中的成功移动记录
"""
return TransferHistory.list_success_move_by_dest(
self._db,
dest=dest,
storage=storage,
recursive=recursive,
return self._execute_sync_query(
lambda session: TransferHistory.list_success_move_by_dest(
session,
dest=dest,
storage=storage,
recursive=recursive,
)
)
def list_by_hash(self, download_hash: str) -> List[TransferHistory]:
@@ -168,7 +194,9 @@ class TransferHistoryOper(DbOper):
按种子hash查询转移记录
:param download_hash: 种子hash
"""
return TransferHistory.list_by_hash(self._db, download_hash)
return self._execute_sync_query(
lambda session: TransferHistory.list_by_hash(session, download_hash)
)
def add(self, **kwargs):
"""
@@ -183,15 +211,21 @@ class TransferHistoryOper(DbOper):
"""
统计最近days天的下载历史数量
"""
return TransferHistory.statistic(self._db, days)
return self._execute_sync_query(
lambda session: TransferHistory.statistic(session, days)
)
async def async_statistic(self, days: int = 7) -> List[Any]:
"""异步统计最近若干天的整理历史数量。"""
return await TransferHistory.async_statistic(self._db, days)
return await self._execute_async_query(
lambda session: TransferHistory.async_statistic(session, days)
)
def monthly_media_statistics(self) -> tuple[int, int, int, int]:
"""统计本月成功整理的电影、剧集、单集和音乐数量。"""
return TransferHistory.monthly_media_statistics(self._db)
return self._execute_sync_query(
TransferHistory.monthly_media_statistics
)
def get_by(self, title: Optional[str] = None, year: Optional[str] = None, mtype: Optional[str] = None,
season: Optional[str] = None, episode: Optional[str] = None,
@@ -200,26 +234,32 @@ class TransferHistoryOper(DbOper):
"""
按类型、标题、年份、季集查询转移记录
"""
return TransferHistory.list_by(db=self._db,
mtype=mtype,
title=title,
dest=dest,
year=year,
season=season,
episode=episode,
media_source=media_source,
media_id=media_id)
return self._execute_sync_query(
lambda session: TransferHistory.list_by(
db=session,
mtype=mtype,
title=title,
dest=dest,
year=year,
season=season,
episode=episode,
media_source=media_source,
media_id=media_id,
)
)
def get_by_media_identity(
self, media_source: MediaSource, media_id: str,
mtype: Optional[str] = None,
) -> Optional[TransferHistory]:
"""按规范媒体身份和类型查询整理记录。"""
return TransferHistory.get_by_media_identity(
db=self._db,
media_source=media_source,
media_id=media_id,
mtype=mtype,
return self._execute_sync_query(
lambda session: TransferHistory.get_by_media_identity(
db=session,
media_source=media_source,
media_id=media_id,
mtype=mtype,
)
)
def delete(self, historyid):
@@ -312,4 +352,6 @@ class TransferHistoryOper(DbOper):
查询某时间之后的转移历史
:param date: 日期
"""
return TransferHistory.list_by_date(self._db, date)
return self._execute_sync_query(
lambda session: TransferHistory.list_by_date(session, date)
)