mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-05 07:27:15 +08:00
fix(database): decouple worker errors from application
This commit is contained in:
Vendored
+13
-7
@@ -2467,14 +2467,15 @@ class PluginHelper(metaclass=WeakSingleton):
|
||||
"""异步恢复主程序运行依赖,避免修复命令绕过可取消进程边界。"""
|
||||
repair_target = snapshot_file
|
||||
repair_desc = "主程序依赖快照"
|
||||
if repair_target and not repair_target.exists():
|
||||
if repair_target and not await _await_thread_operation(repair_target.exists):
|
||||
repair_target = None
|
||||
if repair_target is None:
|
||||
repair_target = settings.ROOT_PATH / "pyproject.toml"
|
||||
repair_desc = "主程序 uv.lock"
|
||||
if not repair_target.exists():
|
||||
if not await _await_thread_operation(repair_target.exists):
|
||||
return False, f"恢复依赖文件不存在:{repair_target}"
|
||||
if snapshot_file is None and not (settings.ROOT_PATH / "uv.lock").exists():
|
||||
lock_file = settings.ROOT_PATH / "uv.lock"
|
||||
if snapshot_file is None and not await _await_thread_operation(lock_file.exists):
|
||||
return False, f"恢复依赖文件不存在:{settings.ROOT_PATH / 'uv.lock'}"
|
||||
|
||||
request = cls.__build_package_install_request(
|
||||
@@ -2568,7 +2569,7 @@ class PluginHelper(metaclass=WeakSingleton):
|
||||
candidate_dirs = []
|
||||
for dependency_file in resolved_dependency_files:
|
||||
wheels_dir = dependency_file.parent / "wheels"
|
||||
if wheels_dir.is_dir():
|
||||
if await _await_thread_operation(wheels_dir.is_dir):
|
||||
candidate_dirs.append(wheels_dir)
|
||||
if find_links_dirs:
|
||||
candidate_dirs.extend(find_links_dirs)
|
||||
@@ -2577,9 +2578,11 @@ class PluginHelper(metaclass=WeakSingleton):
|
||||
seen_dirs = set()
|
||||
for candidate_dir in candidate_dirs:
|
||||
candidate_path = Path(candidate_dir)
|
||||
if not candidate_path.is_dir():
|
||||
if not await _await_thread_operation(candidate_path.is_dir):
|
||||
continue
|
||||
candidate_key = str(candidate_path.resolve())
|
||||
candidate_key = str(
|
||||
await _await_thread_operation(candidate_path.resolve)
|
||||
)
|
||||
if candidate_key in seen_dirs:
|
||||
continue
|
||||
seen_dirs.add(candidate_key)
|
||||
@@ -2707,7 +2710,10 @@ class PluginHelper(metaclass=WeakSingleton):
|
||||
if acquired:
|
||||
cls._package_install_lock.release()
|
||||
if constraints_file:
|
||||
constraints_file.unlink(missing_ok=True)
|
||||
await _await_thread_operation(
|
||||
constraints_file.unlink,
|
||||
missing_ok=True,
|
||||
)
|
||||
|
||||
async def __async_backup_plugin(self, pid: str) -> str:
|
||||
"""
|
||||
|
||||
@@ -57,7 +57,7 @@ from app.api.dependencies.plugin import (
|
||||
from app.adapters.external.server import MoviePilotServerHelper
|
||||
from app.adapters.external.market import PluginHelper
|
||||
from app.adapters.system.plugin.package import PluginPackageManager
|
||||
from app.application.database import DatabaseWorkerOverloadedError
|
||||
from app.schemas.exception import DatabaseWorkerOverloadedError
|
||||
from app.runtime.log import logger
|
||||
from app.schemas.types import SystemConfigKey
|
||||
|
||||
|
||||
@@ -18,14 +18,6 @@ DatabaseProbe = Callable[[], Optional[str]]
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
class DatabaseWorkerClosedError(RuntimeError):
|
||||
"""数据库执行器尚未启动或已经停止。"""
|
||||
|
||||
|
||||
class DatabaseWorkerOverloadedError(RuntimeError):
|
||||
"""数据库执行器的运行与排队容量已经用尽。"""
|
||||
|
||||
|
||||
class AsyncDatabaseExecutor(Protocol):
|
||||
"""让异步业务调用同步短事务而不阻塞事件循环。"""
|
||||
|
||||
|
||||
@@ -10,10 +10,12 @@ from weakref import WeakValueDictionary
|
||||
|
||||
from app.application.database import (
|
||||
AsyncDatabaseExecutor,
|
||||
)
|
||||
from app.schemas.agent import AgentChatSessionDetail, AgentChatSessionSummary
|
||||
from app.schemas.exception import (
|
||||
DatabaseWorkerClosedError,
|
||||
DatabaseWorkerOverloadedError,
|
||||
)
|
||||
from app.schemas.agent import AgentChatSessionDetail, AgentChatSessionSummary
|
||||
from app.runtime.observability import record_metric
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ from collections.abc import Awaitable, Callable
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any, Optional
|
||||
|
||||
from app.application.database import DatabaseWorkerOverloadedError
|
||||
from app.schemas.exception import DatabaseWorkerOverloadedError
|
||||
from app.application.plugin.lifecycle import plugin_lifecycle
|
||||
from app.runtime.log import logger
|
||||
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ from contextvars import copy_context
|
||||
from dataclasses import dataclass
|
||||
from typing import Callable, TypeVar
|
||||
|
||||
from app.application.database import (
|
||||
from app.schemas.exception import (
|
||||
DatabaseWorkerClosedError,
|
||||
DatabaseWorkerOverloadedError,
|
||||
)
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ from app.adapters.observability.otel import build_observation_port
|
||||
from app.adapters.web.plugin.routes import FastAPIDynamicRouteRegistry
|
||||
from app.adapters.web.health import install_health_routes
|
||||
from app.application.plugin.routes import configure_plugin_routes
|
||||
from app.application.database import (
|
||||
from app.schemas.exception import (
|
||||
DatabaseWorkerClosedError,
|
||||
DatabaseWorkerOverloadedError,
|
||||
)
|
||||
|
||||
@@ -47,6 +47,14 @@ class StorageQueryError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class DatabaseWorkerClosedError(RuntimeError):
|
||||
"""数据库执行器尚未启动或已经停止。"""
|
||||
|
||||
|
||||
class DatabaseWorkerOverloadedError(RuntimeError):
|
||||
"""数据库执行器的运行与排队容量已经用尽。"""
|
||||
|
||||
|
||||
class TMDbException(Exception):
|
||||
"""
|
||||
用于表示TheMovieDB数据源请求失败的跨层异常契约。
|
||||
|
||||
@@ -81,6 +81,8 @@ SCHEMA_EXPORTS = {
|
||||
'DashboardMemoryInfo': ('app.schemas.dashboard', 'DashboardMemoryInfo'),
|
||||
'DashboardSystemInfo': ('app.schemas.dashboard', 'DashboardSystemInfo'),
|
||||
'DataT': ('app.schemas.response', 'DataT'),
|
||||
'DatabaseWorkerClosedError': ('app.schemas.exception', 'DatabaseWorkerClosedError'),
|
||||
'DatabaseWorkerOverloadedError': ('app.schemas.exception', 'DatabaseWorkerOverloadedError'),
|
||||
'Dict': ('app.schemas.mcp', 'Dict'),
|
||||
'DiscoverMediaSource': ('app.schemas.event', 'DiscoverMediaSource'),
|
||||
'DiscoverSourceEventData': ('app.schemas.event', 'DiscoverSourceEventData'),
|
||||
|
||||
+18
-7
@@ -13,8 +13,8 @@
|
||||
"runtime_to_db": [],
|
||||
"workflow_to_db": []
|
||||
},
|
||||
"edge_count": 6440,
|
||||
"edge_sha256": "93995005b1d5d1da95e9ec73a39c1d92e8e8e3e3ce3751ce1035e3f31103350d",
|
||||
"edge_count": 6451,
|
||||
"edge_sha256": "9075d8717e384580cd6a41bc36685438770db4a8d8f18c57e6c494f32937113a",
|
||||
"edges": [
|
||||
"app -> app.runtime",
|
||||
"app -> app.runtime.compat",
|
||||
@@ -237,6 +237,8 @@
|
||||
"app.agent.mcp -> app.schemas.types",
|
||||
"app.agent.memory -> app.application",
|
||||
"app.agent.memory -> app.application.agentdata",
|
||||
"app.agent.memory -> app.application.messaging",
|
||||
"app.agent.memory -> app.application.messaging.chat",
|
||||
"app.agent.memory -> app.runtime",
|
||||
"app.agent.memory -> app.runtime.log",
|
||||
"app.agent.memory -> app.runtime.settings",
|
||||
@@ -345,6 +347,8 @@
|
||||
"app.agent.orchestrator -> app.agent.tools.impl.query_system_settings",
|
||||
"app.agent.orchestrator -> app.application",
|
||||
"app.agent.orchestrator -> app.application.agentdata",
|
||||
"app.agent.orchestrator -> app.application.messaging",
|
||||
"app.agent.orchestrator -> app.application.messaging.chat",
|
||||
"app.agent.orchestrator -> app.application.plugin",
|
||||
"app.agent.orchestrator -> app.application.plugin.runtime",
|
||||
"app.agent.orchestrator -> app.chain",
|
||||
@@ -2052,7 +2056,6 @@
|
||||
"app.api.endpoints.plugin -> app.application",
|
||||
"app.api.endpoints.plugin -> app.application.commands",
|
||||
"app.api.endpoints.plugin -> app.application.configuration",
|
||||
"app.api.endpoints.plugin -> app.application.database",
|
||||
"app.api.endpoints.plugin -> app.application.plugin",
|
||||
"app.api.endpoints.plugin -> app.application.plugin.config",
|
||||
"app.api.endpoints.plugin -> app.application.plugin.folders",
|
||||
@@ -2068,6 +2071,7 @@
|
||||
"app.api.endpoints.plugin -> app.runtime.log",
|
||||
"app.api.endpoints.plugin -> app.schemas",
|
||||
"app.api.endpoints.plugin -> app.schemas.common",
|
||||
"app.api.endpoints.plugin -> app.schemas.exception",
|
||||
"app.api.endpoints.plugin -> app.schemas.plugin",
|
||||
"app.api.endpoints.plugin -> app.schemas.response",
|
||||
"app.api.endpoints.plugin -> app.schemas.token",
|
||||
@@ -2553,8 +2557,13 @@
|
||||
"app.application.mediaserver -> app.schemas.types",
|
||||
"app.application.messaging.agent -> app.schemas",
|
||||
"app.application.messaging.agent -> app.schemas.types",
|
||||
"app.application.messaging.chat -> app.application",
|
||||
"app.application.messaging.chat -> app.application.database",
|
||||
"app.application.messaging.chat -> app.runtime",
|
||||
"app.application.messaging.chat -> app.runtime.observability",
|
||||
"app.application.messaging.chat -> app.schemas",
|
||||
"app.application.messaging.chat -> app.schemas.agent",
|
||||
"app.application.messaging.chat -> app.schemas.exception",
|
||||
"app.application.messaging.interaction -> app.schemas",
|
||||
"app.application.messaging.interaction -> app.schemas.message",
|
||||
"app.application.messaging.interaction -> app.schemas.notification",
|
||||
@@ -2641,11 +2650,12 @@
|
||||
"app.application.plugin.folders -> app.schemas",
|
||||
"app.application.plugin.folders -> app.schemas.types",
|
||||
"app.application.plugin.install -> app.application",
|
||||
"app.application.plugin.install -> app.application.database",
|
||||
"app.application.plugin.install -> app.application.plugin",
|
||||
"app.application.plugin.install -> app.application.plugin.lifecycle",
|
||||
"app.application.plugin.install -> app.runtime",
|
||||
"app.application.plugin.install -> app.runtime.log",
|
||||
"app.application.plugin.install -> app.schemas",
|
||||
"app.application.plugin.install -> app.schemas.exception",
|
||||
"app.application.recognition -> app.application",
|
||||
"app.application.recognition -> app.application.configuration",
|
||||
"app.application.recognition -> app.schemas",
|
||||
@@ -3675,10 +3685,10 @@
|
||||
"app.db.session -> app.runtime.config",
|
||||
"app.db.session -> app.runtime.log",
|
||||
"app.db.session -> app.runtime.observability",
|
||||
"app.db.worker -> app.application",
|
||||
"app.db.worker -> app.application.database",
|
||||
"app.db.worker -> app.runtime",
|
||||
"app.db.worker -> app.runtime.observability",
|
||||
"app.db.worker -> app.schemas",
|
||||
"app.db.worker -> app.schemas.exception",
|
||||
"app.doctor.checks -> app.adapters",
|
||||
"app.doctor.checks -> app.adapters.system",
|
||||
"app.doctor.checks -> app.adapters.system.backup",
|
||||
@@ -3802,7 +3812,6 @@
|
||||
"app.factory -> app.api",
|
||||
"app.factory -> app.api.response",
|
||||
"app.factory -> app.application",
|
||||
"app.factory -> app.application.database",
|
||||
"app.factory -> app.application.plugin",
|
||||
"app.factory -> app.application.plugin.routes",
|
||||
"app.factory -> app.application.security",
|
||||
@@ -3816,6 +3825,7 @@
|
||||
"app.factory -> app.runtime.observability",
|
||||
"app.factory -> app.runtime.settings",
|
||||
"app.factory -> app.schemas",
|
||||
"app.factory -> app.schemas.exception",
|
||||
"app.factory -> app.schemas.mcp",
|
||||
"app.factory -> app.schemas.openai",
|
||||
"app.factory -> app.schemas.response",
|
||||
@@ -6094,6 +6104,7 @@
|
||||
"app.startup.modules_initializer -> app.application.history",
|
||||
"app.startup.modules_initializer -> app.application.image",
|
||||
"app.startup.modules_initializer -> app.application.messaging",
|
||||
"app.startup.modules_initializer -> app.application.messaging.agent",
|
||||
"app.startup.modules_initializer -> app.application.messaging.chat",
|
||||
"app.startup.modules_initializer -> app.application.messaging.message",
|
||||
"app.startup.modules_initializer -> app.application.module",
|
||||
|
||||
@@ -11,7 +11,7 @@ from uuid import uuid4
|
||||
import pytest
|
||||
from sqlalchemy import delete, select
|
||||
|
||||
from app.application.database import (
|
||||
from app.schemas.exception import (
|
||||
DatabaseWorkerClosedError,
|
||||
DatabaseWorkerOverloadedError,
|
||||
)
|
||||
|
||||
@@ -23,7 +23,7 @@ from app.factory import (
|
||||
localized_unhandled_exception_handler,
|
||||
localized_validation_exception_handler,
|
||||
)
|
||||
from app.application.database import (
|
||||
from app.schemas.exception import (
|
||||
DatabaseWorkerClosedError,
|
||||
DatabaseWorkerOverloadedError,
|
||||
)
|
||||
|
||||
@@ -6,8 +6,8 @@ from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from app.db.worker import (
|
||||
DatabaseWorker,
|
||||
from app.db.worker import DatabaseWorker
|
||||
from app.schemas.exception import (
|
||||
DatabaseWorkerClosedError,
|
||||
DatabaseWorkerOverloadedError,
|
||||
)
|
||||
|
||||
@@ -3,7 +3,7 @@ from unittest.mock import AsyncMock, Mock
|
||||
|
||||
import pytest
|
||||
|
||||
from app.application.database import DatabaseWorkerOverloadedError
|
||||
from app.schemas.exception import DatabaseWorkerOverloadedError
|
||||
from app.application.plugin.install import PluginInstallCommand
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user