mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-05 07:27:15 +08:00
refactor(sdk): isolate plugin query persistence
This commit is contained in:
+41
-24
@@ -1441,8 +1441,8 @@
|
||||
"runtime_only": true
|
||||
}
|
||||
},
|
||||
"edge_count": 6924,
|
||||
"edge_sha256": "d5471439086bcfdd8060b77670af6f821a34e3a864ba7e2cb7230c599a1cb3bb",
|
||||
"edge_count": 6940,
|
||||
"edge_sha256": "8ff91be099f1230655ceeb006bd1bf604063054ddb0721b3e887c956ea1251fb",
|
||||
"edges": [
|
||||
"app -> app.runtime",
|
||||
"app -> app.runtime.compat",
|
||||
@@ -4008,10 +4008,6 @@
|
||||
"app.application.configuration -> app.schemas.types",
|
||||
"app.application.dashboard -> app.schemas",
|
||||
"app.application.dashboard -> app.schemas.dashboard",
|
||||
"app.application.data_query -> app.application",
|
||||
"app.application.data_query -> app.application.database",
|
||||
"app.application.data_query -> app.schemas",
|
||||
"app.application.data_query -> app.schemas.query",
|
||||
"app.application.directory -> app.adapters",
|
||||
"app.application.directory -> app.adapters.system",
|
||||
"app.application.directory -> app.adapters.system.host",
|
||||
@@ -4264,6 +4260,10 @@
|
||||
"app.application.plugin.transaction -> app.application.database",
|
||||
"app.application.plugin.transaction -> app.application.plugin",
|
||||
"app.application.plugin.transaction -> app.application.plugin.identity",
|
||||
"app.application.query -> app.application",
|
||||
"app.application.query -> app.application.database",
|
||||
"app.application.query -> app.schemas",
|
||||
"app.application.query -> app.schemas.query",
|
||||
"app.application.recognition -> app.application",
|
||||
"app.application.recognition -> app.application.configuration",
|
||||
"app.application.recognition -> app.schemas",
|
||||
@@ -5135,18 +5135,6 @@
|
||||
"app.db.adapters.chain -> app.db.oper.transferpending",
|
||||
"app.db.adapters.chain -> app.db.oper.transfersettlementreceipt",
|
||||
"app.db.adapters.chain -> app.db.uow",
|
||||
"app.db.adapters.data_query -> app.application",
|
||||
"app.db.adapters.data_query -> app.application.data_query",
|
||||
"app.db.adapters.data_query -> app.db",
|
||||
"app.db.adapters.data_query -> app.db.base",
|
||||
"app.db.adapters.data_query -> app.db.models",
|
||||
"app.db.adapters.data_query -> app.db.models.downloadhistory",
|
||||
"app.db.adapters.data_query -> app.db.models.subscribe",
|
||||
"app.db.adapters.data_query -> app.db.models.subscribehistory",
|
||||
"app.db.adapters.data_query -> app.db.models.transferhistory",
|
||||
"app.db.adapters.data_query -> app.schemas",
|
||||
"app.db.adapters.data_query -> app.schemas.query",
|
||||
"app.db.adapters.data_query -> app.schemas.types",
|
||||
"app.db.adapters.download -> app.db",
|
||||
"app.db.adapters.download -> app.db.oper",
|
||||
"app.db.adapters.download -> app.db.oper.downloadfailure",
|
||||
@@ -5176,6 +5164,16 @@
|
||||
"app.db.adapters.plugininstallation -> app.db.models",
|
||||
"app.db.adapters.plugininstallation -> app.db.models.pluginidentity",
|
||||
"app.db.adapters.plugininstallation -> app.db.models.plugininstallation",
|
||||
"app.db.adapters.query -> app.application",
|
||||
"app.db.adapters.query -> app.application.query",
|
||||
"app.db.adapters.query -> app.db",
|
||||
"app.db.adapters.query -> app.db.oper",
|
||||
"app.db.adapters.query -> app.db.oper.downloadhistory",
|
||||
"app.db.adapters.query -> app.db.oper.subscribe",
|
||||
"app.db.adapters.query -> app.db.oper.subscribehistory",
|
||||
"app.db.adapters.query -> app.db.oper.transferhistory",
|
||||
"app.db.adapters.query -> app.schemas",
|
||||
"app.db.adapters.query -> app.schemas.query",
|
||||
"app.db.adapters.site -> app.db",
|
||||
"app.db.adapters.site -> app.db.oper",
|
||||
"app.db.adapters.site -> app.db.oper.site",
|
||||
@@ -5355,7 +5353,10 @@
|
||||
"app.db.oper.downloadhistory -> app.db.base",
|
||||
"app.db.oper.downloadhistory -> app.db.models",
|
||||
"app.db.oper.downloadhistory -> app.db.models.downloadhistory",
|
||||
"app.db.oper.downloadhistory -> app.db.oper",
|
||||
"app.db.oper.downloadhistory -> app.db.oper.query",
|
||||
"app.db.oper.downloadhistory -> app.schemas",
|
||||
"app.db.oper.downloadhistory -> app.schemas.query",
|
||||
"app.db.oper.downloadhistory -> app.schemas.types",
|
||||
"app.db.oper.mediaserver -> app.db",
|
||||
"app.db.oper.mediaserver -> app.db.base",
|
||||
@@ -5380,6 +5381,11 @@
|
||||
"app.db.oper.pluginidentity -> app.db.base",
|
||||
"app.db.oper.pluginidentity -> app.db.models",
|
||||
"app.db.oper.pluginidentity -> app.db.models.pluginidentity",
|
||||
"app.db.oper.query -> app.db",
|
||||
"app.db.oper.query -> app.db.base",
|
||||
"app.db.oper.query -> app.schemas",
|
||||
"app.db.oper.query -> app.schemas.query",
|
||||
"app.db.oper.query -> app.schemas.types",
|
||||
"app.db.oper.site -> app.db",
|
||||
"app.db.oper.site -> app.db.base",
|
||||
"app.db.oper.site -> app.db.models",
|
||||
@@ -5395,12 +5401,19 @@
|
||||
"app.db.oper.subscribe -> app.db.models",
|
||||
"app.db.oper.subscribe -> app.db.models.subscribe",
|
||||
"app.db.oper.subscribe -> app.db.models.subscribehistory",
|
||||
"app.db.oper.subscribe -> app.db.oper",
|
||||
"app.db.oper.subscribe -> app.db.oper.query",
|
||||
"app.db.oper.subscribe -> app.schemas",
|
||||
"app.db.oper.subscribe -> app.schemas.query",
|
||||
"app.db.oper.subscribe -> app.schemas.types",
|
||||
"app.db.oper.subscribehistory -> app.db",
|
||||
"app.db.oper.subscribehistory -> app.db.base",
|
||||
"app.db.oper.subscribehistory -> app.db.models",
|
||||
"app.db.oper.subscribehistory -> app.db.models.subscribehistory",
|
||||
"app.db.oper.subscribehistory -> app.db.oper",
|
||||
"app.db.oper.subscribehistory -> app.db.oper.query",
|
||||
"app.db.oper.subscribehistory -> app.schemas",
|
||||
"app.db.oper.subscribehistory -> app.schemas.query",
|
||||
"app.db.oper.systemconfig -> app.db",
|
||||
"app.db.oper.systemconfig -> app.db.base",
|
||||
"app.db.oper.systemconfig -> app.db.models",
|
||||
@@ -5417,7 +5430,10 @@
|
||||
"app.db.oper.transferhistory -> app.db.base",
|
||||
"app.db.oper.transferhistory -> app.db.models",
|
||||
"app.db.oper.transferhistory -> app.db.models.transferhistory",
|
||||
"app.db.oper.transferhistory -> app.db.oper",
|
||||
"app.db.oper.transferhistory -> app.db.oper.query",
|
||||
"app.db.oper.transferhistory -> app.schemas",
|
||||
"app.db.oper.transferhistory -> app.schemas.query",
|
||||
"app.db.oper.transferhistory -> app.schemas.types",
|
||||
"app.db.oper.transferpending -> app.db",
|
||||
"app.db.oper.transferpending -> app.db.base",
|
||||
@@ -7769,7 +7785,7 @@
|
||||
"app.sdk.plugins -> app.runtime.extensions.module_manager",
|
||||
"app.sdk.plugins -> app.runtime.extensions.plugin_manager",
|
||||
"app.sdk.queries -> app.application",
|
||||
"app.sdk.queries -> app.application.data_query",
|
||||
"app.sdk.queries -> app.application.query",
|
||||
"app.sdk.queries -> app.schemas",
|
||||
"app.sdk.queries -> app.schemas.query",
|
||||
"app.sdk.security -> app.adapters",
|
||||
@@ -7953,7 +7969,6 @@
|
||||
"app.startup.initializers.modules -> app.application.chain.data",
|
||||
"app.startup.initializers.modules -> app.application.chain.events",
|
||||
"app.startup.initializers.modules -> app.application.configuration",
|
||||
"app.startup.initializers.modules -> app.application.data_query",
|
||||
"app.startup.initializers.modules -> app.application.database",
|
||||
"app.startup.initializers.modules -> app.application.history",
|
||||
"app.startup.initializers.modules -> app.application.image",
|
||||
@@ -7966,6 +7981,7 @@
|
||||
"app.startup.initializers.modules -> app.application.plugin",
|
||||
"app.startup.initializers.modules -> app.application.plugin.runtime",
|
||||
"app.startup.initializers.modules -> app.application.plugin.transaction",
|
||||
"app.startup.initializers.modules -> app.application.query",
|
||||
"app.startup.initializers.modules -> app.application.security",
|
||||
"app.startup.initializers.modules -> app.application.security.auth",
|
||||
"app.startup.initializers.modules -> app.application.security.passkey",
|
||||
@@ -7996,11 +8012,11 @@
|
||||
"app.startup.initializers.modules -> app.db",
|
||||
"app.startup.initializers.modules -> app.db.adapters",
|
||||
"app.startup.initializers.modules -> app.db.adapters.chain",
|
||||
"app.startup.initializers.modules -> app.db.adapters.data_query",
|
||||
"app.startup.initializers.modules -> app.db.adapters.download",
|
||||
"app.startup.initializers.modules -> app.db.adapters.outbox",
|
||||
"app.startup.initializers.modules -> app.db.adapters.pluginidentity",
|
||||
"app.startup.initializers.modules -> app.db.adapters.plugininstallation",
|
||||
"app.startup.initializers.modules -> app.db.adapters.query",
|
||||
"app.startup.initializers.modules -> app.db.adapters.site",
|
||||
"app.startup.initializers.modules -> app.db.adapters.subscription",
|
||||
"app.startup.initializers.modules -> app.db.adapters.transaction",
|
||||
@@ -8369,7 +8385,7 @@
|
||||
"app.workflow.actions.transfer_file -> app.workflow",
|
||||
"app.workflow.actions.transfer_file -> app.workflow.actions"
|
||||
],
|
||||
"module_count": 848,
|
||||
"module_count": 849,
|
||||
"modules": [
|
||||
"app",
|
||||
"app.adapters",
|
||||
@@ -8629,7 +8645,6 @@
|
||||
"app.application.commands",
|
||||
"app.application.configuration",
|
||||
"app.application.dashboard",
|
||||
"app.application.data_query",
|
||||
"app.application.database",
|
||||
"app.application.directory",
|
||||
"app.application.download",
|
||||
@@ -8678,6 +8693,7 @@
|
||||
"app.application.plugin.runtime",
|
||||
"app.application.plugin.source",
|
||||
"app.application.plugin.transaction",
|
||||
"app.application.query",
|
||||
"app.application.recognition",
|
||||
"app.application.rss",
|
||||
"app.application.rules",
|
||||
@@ -8762,11 +8778,11 @@
|
||||
"app.db",
|
||||
"app.db.adapters",
|
||||
"app.db.adapters.chain",
|
||||
"app.db.adapters.data_query",
|
||||
"app.db.adapters.download",
|
||||
"app.db.adapters.outbox",
|
||||
"app.db.adapters.pluginidentity",
|
||||
"app.db.adapters.plugininstallation",
|
||||
"app.db.adapters.query",
|
||||
"app.db.adapters.site",
|
||||
"app.db.adapters.subscription",
|
||||
"app.db.adapters.transaction",
|
||||
@@ -8819,6 +8835,7 @@
|
||||
"app.db.oper.passkey",
|
||||
"app.db.oper.plugindata",
|
||||
"app.db.oper.pluginidentity",
|
||||
"app.db.oper.query",
|
||||
"app.db.oper.site",
|
||||
"app.db.oper.subscribe",
|
||||
"app.db.oper.subscribehistory",
|
||||
|
||||
@@ -467,18 +467,12 @@
|
||||
"app/db/models/workflow.py": {
|
||||
"I001": 1
|
||||
},
|
||||
"app/db/oper/downloadhistory.py": {
|
||||
"I001": 1
|
||||
},
|
||||
"app/db/oper/message.py": {
|
||||
"I001": 1
|
||||
},
|
||||
"app/db/oper/site.py": {
|
||||
"I001": 1
|
||||
},
|
||||
"app/db/oper/subscribe.py": {
|
||||
"I001": 1
|
||||
},
|
||||
"app/db/oper/systemconfig.py": {
|
||||
"I001": 1
|
||||
},
|
||||
@@ -1128,9 +1122,6 @@
|
||||
"tests/test_agent_lazy_runtime_boundary.py": {
|
||||
"F401": 1
|
||||
},
|
||||
"tests/test_agent_lifecycle.py": {
|
||||
"I001": 1
|
||||
},
|
||||
"tests/test_agent_llm_capability.py": {
|
||||
"I001": 1
|
||||
},
|
||||
|
||||
@@ -4,18 +4,19 @@ from unittest.mock import AsyncMock, MagicMock
|
||||
import pytest
|
||||
|
||||
import app.agent.orchestrator as agent_module
|
||||
from app.application.messaging.agent import (
|
||||
create_web_agent_background_task,
|
||||
shutdown_web_agent_background_tasks,
|
||||
)
|
||||
from app.agent.memory import MemoryManager
|
||||
from app.agent.orchestrator import (
|
||||
AGENT_SESSION_QUEUE_MAX_SIZE,
|
||||
AgentManager,
|
||||
AgentManagerQueueFullError,
|
||||
AgentManagerUnavailableError,
|
||||
)
|
||||
from app.agent.memory import MemoryManager
|
||||
from app.agent.tools.base import reopen_blocking_executors
|
||||
from app.application.messaging.agent import (
|
||||
create_web_agent_background_task,
|
||||
shutdown_web_agent_background_tasks,
|
||||
)
|
||||
from app.application.query import get_configured_data_query_service
|
||||
from app.startup.initializers import agent as agent_initializer
|
||||
from app.startup.initializers import modules as modules_initializer
|
||||
|
||||
@@ -202,6 +203,9 @@ async def test_agent_initialization_failure_does_not_stop_module_startup(
|
||||
assert runtime.workflow.system_config() is (
|
||||
modules_initializer.get_configured_system_config()
|
||||
)
|
||||
query_page = get_configured_data_query_service().list_subscriptions({"ids": [-1]})
|
||||
assert query_page.items == []
|
||||
assert query_page.total == 0
|
||||
finally:
|
||||
await modules_initializer.stop_database_worker()
|
||||
|
||||
|
||||
@@ -61,9 +61,9 @@ class _RecordingExecutor:
|
||||
@pytest.fixture
|
||||
def query_sdk(db, monkeypatch):
|
||||
"""装配真实数据查询适配器,并把 SDK 绑定到本用例的 SQLite 服务。"""
|
||||
from app.application import data_query as data_query_module
|
||||
from app.application.data_query import DataQueryService
|
||||
from app.db.adapters.data_query import SqlAlchemyDataQueryAdapter
|
||||
from app.application import query as data_query_module
|
||||
from app.application.query import DataQueryService
|
||||
from app.db.adapters.query import SqlAlchemyDataQueryAdapter
|
||||
from app.db.session import SessionFactory
|
||||
from app.sdk import queries as sdk
|
||||
|
||||
@@ -180,7 +180,7 @@ def _transfer_history(
|
||||
episodes: str | None = "E01",
|
||||
download_hash: str | None = "hash-1",
|
||||
episode_group: str | None = None,
|
||||
status: bool = True,
|
||||
status: bool | None = True,
|
||||
date: str = "2026-08-27 10:00:00",
|
||||
mtype: str = MediaType.TV.value,
|
||||
) -> TransferHistoryModel:
|
||||
@@ -630,6 +630,67 @@ def test_snapshots_normalize_legacy_identity_and_transfer_status():
|
||||
assert snapshot.status is False
|
||||
|
||||
|
||||
def test_transfer_failure_filter_includes_legacy_null_status(db, query_sdk):
|
||||
"""失败筛选与快照语义一致,包含状态尚未回填的旧整理记录。"""
|
||||
sdk, _executor = query_sdk
|
||||
legacy_row = db.add(
|
||||
_transfer_history(
|
||||
"Legacy null status",
|
||||
media_id="legacy-status",
|
||||
src="/legacy/status-src.mkv",
|
||||
dest="/legacy/status-dest.mkv",
|
||||
status=None,
|
||||
)
|
||||
)
|
||||
legacy_row.status = None
|
||||
db.session.commit()
|
||||
|
||||
page = sdk.list_transfer_history(
|
||||
TransferHistoryFilter(
|
||||
media_source=TMDB,
|
||||
media_id="legacy-status",
|
||||
status=False,
|
||||
)
|
||||
)
|
||||
|
||||
assert [item.id for item in page.items] == [legacy_row.id]
|
||||
assert page.items[0].status is False
|
||||
|
||||
|
||||
def test_transfer_required_identity_excludes_unparseable_legacy_source(db, query_sdk):
|
||||
"""有效身份筛选不得返回随后会被快照降级为空身份的脏来源。"""
|
||||
sdk, _executor = query_sdk
|
||||
valid_row = db.add(
|
||||
_transfer_history(
|
||||
"Valid dynamic source",
|
||||
media_id="valid-dynamic",
|
||||
src="/valid/source.mkv",
|
||||
dest="/valid/dest.mkv",
|
||||
)
|
||||
)
|
||||
invalid_row = db.add(
|
||||
_transfer_history(
|
||||
"Invalid legacy source",
|
||||
media_id="invalid-source",
|
||||
src="/invalid/source.mkv",
|
||||
dest="/invalid/dest.mkv",
|
||||
)
|
||||
)
|
||||
valid_row.media_source = "plugin-source"
|
||||
invalid_row.media_source = "invalid!"
|
||||
db.session.commit()
|
||||
|
||||
page = sdk.list_transfer_history(
|
||||
TransferHistoryFilter(
|
||||
ids=(valid_row.id, invalid_row.id),
|
||||
require_media_identity=True,
|
||||
)
|
||||
)
|
||||
|
||||
assert [item.id for item in page.items] == [valid_row.id]
|
||||
assert page.items[0].media_source == MediaSource("plugin-source")
|
||||
|
||||
|
||||
def test_query_snapshots_are_owned_by_the_sdk_contract_module():
|
||||
"""公开查询返回值由独立快照定义,不复用宿主写入或 API 响应模型。"""
|
||||
snapshots = (
|
||||
|
||||
Reference in New Issue
Block a user