mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-05 23:47:41 +08:00
refactor(database): isolate configuration transactions
This commit is contained in:
@@ -4,9 +4,11 @@ from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from functools import partial
|
||||
from pathlib import Path
|
||||
from typing import Any, Optional, Protocol
|
||||
|
||||
from app.application.database import AsyncDatabaseExecutor
|
||||
from app.schemas.types import MediaType
|
||||
|
||||
|
||||
@@ -16,9 +18,6 @@ class SystemConfigReader(Protocol):
|
||||
def get(self, key: Any = None) -> Any:
|
||||
"""读取配置。"""
|
||||
|
||||
async def async_get(self, key: Any = None) -> Any:
|
||||
"""异步读取配置。"""
|
||||
|
||||
|
||||
class SystemConfigWriter(Protocol):
|
||||
"""持久化用户配置的最小写入端口。"""
|
||||
@@ -26,9 +25,6 @@ class SystemConfigWriter(Protocol):
|
||||
def set(self, key: Any, value: Any) -> bool | None:
|
||||
"""写入配置。"""
|
||||
|
||||
async def async_set(self, key: Any, value: Any) -> bool | None:
|
||||
"""异步写入配置。"""
|
||||
|
||||
def delete(self, key: Any) -> Any:
|
||||
"""删除配置。"""
|
||||
|
||||
@@ -296,14 +292,16 @@ class SystemConfigService:
|
||||
*,
|
||||
reader: SystemConfigReader | None = None,
|
||||
writer: SystemConfigWriter | None = None,
|
||||
async_executor: AsyncDatabaseExecutor | None = None,
|
||||
) -> None:
|
||||
"""注入可分离的读写端口,并兼容旧的单仓储装配参数。"""
|
||||
"""注入读写端口及可选的异步事务执行能力。"""
|
||||
resolved_reader = reader or repository
|
||||
resolved_writer = writer or repository
|
||||
if resolved_reader is None or resolved_writer is None:
|
||||
raise ValueError("系统配置服务必须同时提供 reader 与 writer")
|
||||
self._reader = resolved_reader
|
||||
self._writer = resolved_writer
|
||||
self._async_executor = async_executor
|
||||
|
||||
def get(self, key: Any = None) -> Any:
|
||||
"""读取配置。"""
|
||||
@@ -313,13 +311,11 @@ class SystemConfigService:
|
||||
"""写入配置。"""
|
||||
return self._writer.set(key, value)
|
||||
|
||||
async def async_get(self, key: Any = None) -> Any:
|
||||
"""异步读取配置。"""
|
||||
return await self._reader.async_get(key)
|
||||
|
||||
async def async_set(self, key: Any, value: Any) -> bool | None:
|
||||
"""异步写入配置。"""
|
||||
return await self._writer.async_set(key, value)
|
||||
"""异步写入配置,并等待数据库提交或回滚完成。"""
|
||||
if self._async_executor is None:
|
||||
raise RuntimeError("系统配置异步数据库执行端口尚未配置")
|
||||
return await self._async_executor.run(partial(self._writer.set, key, value))
|
||||
|
||||
def delete(self, key: Any) -> Any:
|
||||
"""删除配置。"""
|
||||
|
||||
@@ -3,17 +3,27 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from typing import Any, Optional
|
||||
from typing import TYPE_CHECKING, Any, Optional, Protocol, TypeVar
|
||||
|
||||
from app.application.backup import (
|
||||
BackupArtifact,
|
||||
BackupVerification,
|
||||
DatabaseBackupService,
|
||||
)
|
||||
from app.application.maintenance import DataCleanupService
|
||||
if TYPE_CHECKING:
|
||||
from app.application.backup import (
|
||||
BackupArtifact,
|
||||
BackupVerification,
|
||||
DatabaseBackupService,
|
||||
)
|
||||
from app.application.maintenance import DataCleanupService
|
||||
|
||||
|
||||
DatabaseProbe = Callable[[], Optional[str]]
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
class AsyncDatabaseExecutor(Protocol):
|
||||
"""让异步业务调用同步短事务而不阻塞事件循环。"""
|
||||
|
||||
async def run(self, operation: Callable[[], T]) -> T:
|
||||
"""等待数据库操作完成提交或回滚,并返回执行结果。"""
|
||||
...
|
||||
|
||||
|
||||
class DatabaseHealthService:
|
||||
|
||||
@@ -2,8 +2,11 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from functools import partial
|
||||
from typing import Any, Protocol
|
||||
|
||||
from app.application.database import AsyncDatabaseExecutor
|
||||
|
||||
|
||||
class UserConfigurationRepository(Protocol):
|
||||
"""用户配置数据端口。"""
|
||||
@@ -18,9 +21,15 @@ class UserConfigurationRepository(Protocol):
|
||||
class UserConfigurationService:
|
||||
"""编排用户个性化配置读写。"""
|
||||
|
||||
def __init__(self, repository: UserConfigurationRepository) -> None:
|
||||
"""注入用户配置数据端口。"""
|
||||
def __init__(
|
||||
self,
|
||||
repository: UserConfigurationRepository,
|
||||
*,
|
||||
async_executor: AsyncDatabaseExecutor | None = None,
|
||||
) -> None:
|
||||
"""注入用户配置数据端口及可选的异步事务执行能力。"""
|
||||
self._repository = repository
|
||||
self._async_executor = async_executor
|
||||
|
||||
def get(self, username: str, key: str) -> Any:
|
||||
"""读取用户配置。"""
|
||||
@@ -30,6 +39,14 @@ class UserConfigurationService:
|
||||
"""写入用户配置。"""
|
||||
return self._repository.set(username=username, key=key, value=value)
|
||||
|
||||
async def async_set(self, username: str, key: str, value: Any) -> Any:
|
||||
"""异步写入用户配置,并等待数据库提交或回滚完成。"""
|
||||
if self._async_executor is None:
|
||||
raise RuntimeError("用户配置异步数据库执行端口尚未配置")
|
||||
return await self._async_executor.run(
|
||||
partial(self._repository.set, username=username, key=key, value=value)
|
||||
)
|
||||
|
||||
|
||||
_configured_user_configuration: UserConfigurationService | None = None
|
||||
|
||||
|
||||
Reference in New Issue
Block a user