mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-04 23:17:20 +08:00
refactor: unify runtime facade governance
This commit is contained in:
+112
-112
@@ -1,41 +1,41 @@
|
||||
{
|
||||
"schema_version": 2,
|
||||
"generated_at": "2026-08-23T15:39:20.210777+00:00",
|
||||
"generated_at": "2026-08-24T04:25:54.827827+00:00",
|
||||
"platform": "macOS-26.5.2-arm64-arm-64bit-Mach-O",
|
||||
"python": "3.14.3",
|
||||
"repeat": 3,
|
||||
"targets": {
|
||||
"app.startup.lifecycle": {
|
||||
"loaded_app_module_count": 356,
|
||||
"max_ms": 914.989,
|
||||
"median_ms": 909.991,
|
||||
"min_ms": 907.871,
|
||||
"loaded_app_module_count": 357,
|
||||
"max_ms": 968.725,
|
||||
"median_ms": 937.268,
|
||||
"min_ms": 933.205,
|
||||
"samples_ms": [
|
||||
914.989,
|
||||
907.871,
|
||||
909.991
|
||||
933.205,
|
||||
937.268,
|
||||
968.725
|
||||
]
|
||||
},
|
||||
"app.factory": {
|
||||
"loaded_app_module_count": 368,
|
||||
"max_ms": 916.407,
|
||||
"median_ms": 914.085,
|
||||
"min_ms": 913.804,
|
||||
"loaded_app_module_count": 369,
|
||||
"max_ms": 943.204,
|
||||
"median_ms": 941.996,
|
||||
"min_ms": 937.878,
|
||||
"samples_ms": [
|
||||
916.407,
|
||||
913.804,
|
||||
914.085
|
||||
941.996,
|
||||
943.204,
|
||||
937.878
|
||||
]
|
||||
},
|
||||
"app.main": {
|
||||
"loaded_app_module_count": 370,
|
||||
"max_ms": 1096.074,
|
||||
"median_ms": 1051.665,
|
||||
"min_ms": 1050.168,
|
||||
"loaded_app_module_count": 371,
|
||||
"max_ms": 1068.791,
|
||||
"median_ms": 1064.912,
|
||||
"min_ms": 1053.947,
|
||||
"samples_ms": [
|
||||
1051.665,
|
||||
1050.168,
|
||||
1096.074
|
||||
1053.947,
|
||||
1068.791,
|
||||
1064.912
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -47,24 +47,24 @@
|
||||
{
|
||||
"mode": "normal",
|
||||
"enabled_component_count": 23,
|
||||
"startup_ms": 0.672,
|
||||
"full_lifespan_ms": 0.831,
|
||||
"startup_ms": 0.629,
|
||||
"full_lifespan_ms": 0.781,
|
||||
"stage_ms": {
|
||||
"后台任务登记器": 0.081,
|
||||
"数据库准备": 0.037,
|
||||
"HTTP 基础能力": 0.035,
|
||||
"领域依赖装配": 0.029,
|
||||
"数据库引擎预热": 0.025,
|
||||
"后台任务登记器": 0.079,
|
||||
"数据库准备": 0.038,
|
||||
"HTTP 基础能力": 0.031,
|
||||
"领域依赖装配": 0.028,
|
||||
"数据库引擎预热": 0.024,
|
||||
"数据库连接预算": 0.024,
|
||||
"路由": 0.022,
|
||||
"模块服务": 0.024,
|
||||
"插件备份恢复": 0.022,
|
||||
"插件": 0.02,
|
||||
"定时器": 0.032,
|
||||
"监控器": 0.022,
|
||||
"待处理整理回放": 0.019,
|
||||
"路由": 0.024,
|
||||
"模块服务": 0.023,
|
||||
"插件备份恢复": 0.02,
|
||||
"插件": 0.023,
|
||||
"定时器": 0.024,
|
||||
"监控器": 0.021,
|
||||
"待处理整理回放": 0.022,
|
||||
"命令服务": 0.023,
|
||||
"工作流": 0.023,
|
||||
"工作流": 0.02,
|
||||
"插件同步与启动收尾": 0.033
|
||||
},
|
||||
"threads_before": 2,
|
||||
@@ -78,25 +78,25 @@
|
||||
{
|
||||
"mode": "normal",
|
||||
"enabled_component_count": 23,
|
||||
"startup_ms": 0.598,
|
||||
"full_lifespan_ms": 0.742,
|
||||
"startup_ms": 0.628,
|
||||
"full_lifespan_ms": 0.778,
|
||||
"stage_ms": {
|
||||
"后台任务登记器": 0.069,
|
||||
"数据库准备": 0.042,
|
||||
"HTTP 基础能力": 0.033,
|
||||
"领域依赖装配": 0.031,
|
||||
"数据库引擎预热": 0.025,
|
||||
"后台任务登记器": 0.079,
|
||||
"数据库准备": 0.037,
|
||||
"HTTP 基础能力": 0.029,
|
||||
"领域依赖装配": 0.032,
|
||||
"数据库引擎预热": 0.023,
|
||||
"数据库连接预算": 0.022,
|
||||
"路由": 0.021,
|
||||
"路由": 0.024,
|
||||
"模块服务": 0.021,
|
||||
"插件备份恢复": 0.021,
|
||||
"插件": 0.019,
|
||||
"插件备份恢复": 0.024,
|
||||
"插件": 0.021,
|
||||
"定时器": 0.024,
|
||||
"监控器": 0.023,
|
||||
"待处理整理回放": 0.019,
|
||||
"命令服务": 0.021,
|
||||
"工作流": 0.023,
|
||||
"插件同步与启动收尾": 0.03
|
||||
"监控器": 0.019,
|
||||
"待处理整理回放": 0.022,
|
||||
"命令服务": 0.022,
|
||||
"工作流": 0.022,
|
||||
"插件同步与启动收尾": 0.033
|
||||
},
|
||||
"threads_before": 2,
|
||||
"threads_started": 2,
|
||||
@@ -109,25 +109,25 @@
|
||||
{
|
||||
"mode": "normal",
|
||||
"enabled_component_count": 23,
|
||||
"startup_ms": 0.765,
|
||||
"full_lifespan_ms": 0.951,
|
||||
"startup_ms": 0.658,
|
||||
"full_lifespan_ms": 0.836,
|
||||
"stage_ms": {
|
||||
"后台任务登记器": 0.088,
|
||||
"数据库准备": 0.067,
|
||||
"HTTP 基础能力": 0.094,
|
||||
"领域依赖装配": 0.039,
|
||||
"数据库引擎预热": 0.031,
|
||||
"数据库连接预算": 0.022,
|
||||
"路由": 0.024,
|
||||
"模块服务": 0.027,
|
||||
"后台任务登记器": 0.081,
|
||||
"数据库准备": 0.044,
|
||||
"HTTP 基础能力": 0.029,
|
||||
"领域依赖装配": 0.04,
|
||||
"数据库引擎预热": 0.024,
|
||||
"数据库连接预算": 0.023,
|
||||
"路由": 0.025,
|
||||
"模块服务": 0.02,
|
||||
"插件备份恢复": 0.024,
|
||||
"插件": 0.021,
|
||||
"定时器": 0.026,
|
||||
"插件": 0.02,
|
||||
"定时器": 0.022,
|
||||
"监控器": 0.023,
|
||||
"待处理整理回放": 0.023,
|
||||
"命令服务": 0.023,
|
||||
"工作流": 0.023,
|
||||
"插件同步与启动收尾": 0.062
|
||||
"待处理整理回放": 0.022,
|
||||
"命令服务": 0.022,
|
||||
"工作流": 0.022,
|
||||
"插件同步与启动收尾": 0.031
|
||||
},
|
||||
"threads_before": 2,
|
||||
"threads_started": 2,
|
||||
@@ -138,8 +138,8 @@
|
||||
"database_connections_started": 0
|
||||
}
|
||||
],
|
||||
"median_startup_ms": 0.672,
|
||||
"median_full_lifespan_ms": 0.831,
|
||||
"median_startup_ms": 0.629,
|
||||
"median_full_lifespan_ms": 0.781,
|
||||
"enabled_component_count": 23,
|
||||
"enabled_components": [
|
||||
"后台任务登记器",
|
||||
@@ -172,41 +172,17 @@
|
||||
{
|
||||
"mode": "safe",
|
||||
"enabled_component_count": 11,
|
||||
"startup_ms": 0.465,
|
||||
"full_lifespan_ms": 0.605,
|
||||
"startup_ms": 0.567,
|
||||
"full_lifespan_ms": 0.734,
|
||||
"stage_ms": {
|
||||
"后台任务登记器": 0.072,
|
||||
"数据库准备": 0.047,
|
||||
"HTTP 基础能力": 0.035,
|
||||
"领域依赖装配": 0.03,
|
||||
"数据库引擎预热": 0.024,
|
||||
"数据库连接预算": 0.022,
|
||||
"路由": 0.023,
|
||||
"模块服务": 0.022,
|
||||
"插件同步与启动收尾": 0.031
|
||||
},
|
||||
"threads_before": 2,
|
||||
"threads_started": 2,
|
||||
"threads_after": 2,
|
||||
"tasks_before": 1,
|
||||
"tasks_started": 2,
|
||||
"tasks_after": 1,
|
||||
"database_connections_started": 0
|
||||
},
|
||||
{
|
||||
"mode": "safe",
|
||||
"enabled_component_count": 11,
|
||||
"startup_ms": 0.478,
|
||||
"full_lifespan_ms": 0.647,
|
||||
"stage_ms": {
|
||||
"后台任务登记器": 0.083,
|
||||
"数据库准备": 0.038,
|
||||
"后台任务登记器": 0.095,
|
||||
"数据库准备": 0.05,
|
||||
"HTTP 基础能力": 0.034,
|
||||
"领域依赖装配": 0.025,
|
||||
"数据库引擎预热": 0.022,
|
||||
"数据库连接预算": 0.025,
|
||||
"路由": 0.025,
|
||||
"模块服务": 0.025,
|
||||
"领域依赖装配": 0.032,
|
||||
"数据库引擎预热": 0.026,
|
||||
"数据库连接预算": 0.031,
|
||||
"路由": 0.026,
|
||||
"模块服务": 0.02,
|
||||
"插件同步与启动收尾": 0.052
|
||||
},
|
||||
"threads_before": 2,
|
||||
@@ -220,17 +196,41 @@
|
||||
{
|
||||
"mode": "safe",
|
||||
"enabled_component_count": 11,
|
||||
"startup_ms": 0.477,
|
||||
"full_lifespan_ms": 0.651,
|
||||
"startup_ms": 0.465,
|
||||
"full_lifespan_ms": 0.61,
|
||||
"stage_ms": {
|
||||
"后台任务登记器": 0.074,
|
||||
"数据库准备": 0.044,
|
||||
"后台任务登记器": 0.078,
|
||||
"数据库准备": 0.037,
|
||||
"HTTP 基础能力": 0.029,
|
||||
"领域依赖装配": 0.029,
|
||||
"数据库引擎预热": 0.027,
|
||||
"数据库连接预算": 0.023,
|
||||
"数据库引擎预热": 0.026,
|
||||
"数据库连接预算": 0.024,
|
||||
"路由": 0.022,
|
||||
"模块服务": 0.021,
|
||||
"模块服务": 0.02,
|
||||
"插件同步与启动收尾": 0.034
|
||||
},
|
||||
"threads_before": 2,
|
||||
"threads_started": 2,
|
||||
"threads_after": 2,
|
||||
"tasks_before": 1,
|
||||
"tasks_started": 2,
|
||||
"tasks_after": 1,
|
||||
"database_connections_started": 0
|
||||
},
|
||||
{
|
||||
"mode": "safe",
|
||||
"enabled_component_count": 11,
|
||||
"startup_ms": 0.456,
|
||||
"full_lifespan_ms": 0.628,
|
||||
"stage_ms": {
|
||||
"后台任务登记器": 0.076,
|
||||
"数据库准备": 0.036,
|
||||
"HTTP 基础能力": 0.029,
|
||||
"领域依赖装配": 0.027,
|
||||
"数据库引擎预热": 0.023,
|
||||
"数据库连接预算": 0.024,
|
||||
"路由": 0.024,
|
||||
"模块服务": 0.022,
|
||||
"插件同步与启动收尾": 0.057
|
||||
},
|
||||
"threads_before": 2,
|
||||
@@ -242,8 +242,8 @@
|
||||
"database_connections_started": 0
|
||||
}
|
||||
],
|
||||
"median_startup_ms": 0.477,
|
||||
"median_full_lifespan_ms": 0.647,
|
||||
"median_startup_ms": 0.465,
|
||||
"median_full_lifespan_ms": 0.628,
|
||||
"enabled_component_count": 11,
|
||||
"enabled_components": [
|
||||
"后台任务登记器",
|
||||
|
||||
@@ -33,6 +33,7 @@ def test_unit_test_workflow_has_independent_host_architecture_gate():
|
||||
assert "tests/test_architecture_dependencies.py" in commands
|
||||
assert "tests/test_architecture_contract_baseline.py" in commands
|
||||
assert "scripts/architecture/baseline.py --check-host" in commands
|
||||
assert "scripts/architecture/service_locator.py" in commands
|
||||
assert "scripts/startup/performance.py --check --repeat 3" in commands
|
||||
|
||||
|
||||
|
||||
@@ -1295,68 +1295,6 @@ def test_agent_tools_do_not_import_entrypoint_internals():
|
||||
assert violations == {}
|
||||
|
||||
|
||||
def test_runtime_consumers_use_scheduler_application_facade():
|
||||
"""非组合根消费者必须经 application Facade 访问进程级 Scheduler。"""
|
||||
allowed = {
|
||||
"app.scheduler",
|
||||
"app.startup.initializers.modules",
|
||||
"app.startup.initializers.scheduler",
|
||||
}
|
||||
violations = {
|
||||
module_name: dependencies & {"app.scheduler"}
|
||||
for module_name, dependencies in _build_module_graph().items()
|
||||
if module_name not in allowed and "app.scheduler" in dependencies
|
||||
}
|
||||
|
||||
assert violations == {}
|
||||
|
||||
|
||||
def test_runtime_consumers_use_plugin_application_facade():
|
||||
"""插件 concrete 管理器只允许组合根和兼容 SDK 直接依赖。"""
|
||||
allowed = {
|
||||
"app.sdk.plugins",
|
||||
"app.startup.initializers.modules",
|
||||
"app.startup.initializers.plugins",
|
||||
}
|
||||
violations = {
|
||||
module_name: dependencies & {"app.runtime.extensions.plugin_manager"}
|
||||
for module_name, dependencies in _build_module_graph().items()
|
||||
if module_name not in allowed
|
||||
and "app.runtime.extensions.plugin_manager" in dependencies
|
||||
}
|
||||
|
||||
assert violations == {}
|
||||
|
||||
|
||||
def test_runtime_consumers_use_command_application_facade():
|
||||
"""Command concrete 实现只允许 startup 组合根直接依赖。"""
|
||||
allowed = {
|
||||
"app.startup.initializers.command",
|
||||
"app.startup.initializers.modules",
|
||||
}
|
||||
violations = {
|
||||
module_name: dependencies & {"app.command"}
|
||||
for module_name, dependencies in _build_module_graph().items()
|
||||
if module_name not in allowed and "app.command" in dependencies
|
||||
}
|
||||
|
||||
assert violations == {}
|
||||
|
||||
|
||||
def test_runtime_consumers_use_workflow_application_facade():
|
||||
"""WorkFlowManager concrete 实现只允许 startup 组合根直接依赖。"""
|
||||
allowed = {"app.startup.initializers.workflow"}
|
||||
violations = {
|
||||
module_name: dependencies & {"app.workflow"}
|
||||
for module_name, dependencies in _build_module_graph().items()
|
||||
if not module_name.startswith("app.workflow")
|
||||
and module_name not in allowed
|
||||
and "app.workflow" in dependencies
|
||||
}
|
||||
|
||||
assert violations == {}
|
||||
|
||||
|
||||
def test_modules_read_deployment_settings_through_runtime_port():
|
||||
"""宿主 Module 不得绕过 runtime 配置端口直接依赖 Settings 实例。"""
|
||||
violations: list[str] = []
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
"""进程级运行时 Facade 静态门禁回归测试。"""
|
||||
|
||||
from scripts.architecture.service_locator import (
|
||||
collect_service_locator_violations,
|
||||
)
|
||||
|
||||
|
||||
def test_host_runtime_consumers_use_application_facades() -> None:
|
||||
"""canonical 宿主不得在批准边界外直接定位 concrete 运行时。"""
|
||||
assert collect_service_locator_violations() == []
|
||||
|
||||
|
||||
def test_service_locator_gate_detects_each_concrete_runtime_family() -> None:
|
||||
"""单一扫描器必须覆盖五类运行时,并保留明确兼容边界。"""
|
||||
graph = {
|
||||
"app.api.scheduler_bypass": {"app.scheduler"},
|
||||
"app.api.module_bypass": {"app.runtime.extensions.module_manager"},
|
||||
"app.api.plugin_bypass": {"app.runtime.extensions.plugin_manager"},
|
||||
"app.api.command_bypass": {"app.command"},
|
||||
"app.api.workflow_bypass": {"app.workflow"},
|
||||
"app.sdk.plugins": {
|
||||
"app.runtime.extensions.module_manager",
|
||||
"app.runtime.extensions.plugin_manager",
|
||||
},
|
||||
"app.startup.initializers.modules": {
|
||||
"app.command",
|
||||
"app.runtime.extensions.module_manager",
|
||||
"app.runtime.extensions.plugin_manager",
|
||||
"app.scheduler",
|
||||
},
|
||||
"app.workflow.manager": {"app.workflow"},
|
||||
}
|
||||
|
||||
violations = collect_service_locator_violations(graph)
|
||||
|
||||
assert [violation.policy for violation in violations] == [
|
||||
"command",
|
||||
"module",
|
||||
"plugin",
|
||||
"scheduler",
|
||||
"workflow",
|
||||
]
|
||||
assert all(violation.source.startswith("app.api.") for violation in violations)
|
||||
Reference in New Issue
Block a user