refactor: strengthen architecture CI gates and runtime contracts

This commit is contained in:
jxxghp
2026-08-25 17:02:29 +08:00
parent 605bf8174a
commit b914e8b6e4
123 changed files with 4240 additions and 1342 deletions
+3 -4
View File
@@ -4,15 +4,13 @@ from collections.abc import AsyncGenerator, Callable, Generator
from dataclasses import dataclass, field
from typing import Protocol
from app.runtime.tasks import TaskRegistry
from app.application.configuration import RuntimeConfiguration, RuntimeSettingsService
from app.application.messaging.chat import (
AsyncAgentChatRepository,
AgentChatPersistenceService,
AsyncAgentChatRepository,
AsyncUnitOfWork,
)
from app.application.outbox import AsyncOutboxTransaction
from app.application.configuration import RuntimeConfiguration, RuntimeSettingsService
from app.application.subscription.delete import SubscribeDeletionRepository
from app.application.subscription.identity import SubscribeIdentityDeletionRepository
from app.application.subscription.mutation import (
@@ -20,6 +18,7 @@ from app.application.subscription.mutation import (
SubscriptionMutationRepository,
)
from app.application.workflow import WorkflowCachePort
from app.runtime.tasks import TaskRegistry
class AgentChatRepositoryFactory(Protocol):
+9 -4
View File
@@ -1,15 +1,19 @@
from typing import Any
from app.agent.llm.gateway import register_llm_provider_runtime
from app.agent.runtime_loader import (
activate_agent_service,
begin_agent_shutdown,
close_materialized_terminal_sessions,
get_agent_manager as get_runtime_agent_manager,
get_running_agent_manager as get_runtime_running_agent_manager,
is_tool_factory_materialized,
reconcile_agent_service,
)
from app.agent.llm.gateway import register_llm_provider_runtime
from app.agent.runtime_loader import (
get_agent_manager as get_runtime_agent_manager,
)
from app.agent.runtime_loader import (
get_running_agent_manager as get_runtime_running_agent_manager,
)
from app.application.agent import register_agent_service_providers
from app.application.messaging.skill import register_skill_catalog_provider
from app.runtime.settings import RuntimeSettingsCompat
@@ -19,7 +23,6 @@ from app.runtime.events import Event, eventmanager
from app.runtime.log import logger
from app.schemas.types import EventType
AGENT_BLOCKING_EXECUTOR_SHUTDOWN_TIMEOUT_SECONDS = 10.0
@@ -226,6 +229,8 @@ async def stop_agent() -> bool:
if is_tool_factory_materialized():
from app.agent.tools.base import (
begin_blocking_executor_shutdown,
)
from app.agent.tools.base import (
close_blocking_executors as close_executors,
)
+1 -1
View File
@@ -1,6 +1,6 @@
import traceback
from collections.abc import Callable
from configparser import ConfigParser as _ConfigParser
import traceback
from alembic.command import upgrade
from alembic.config import Config
+1 -1
View File
@@ -1,3 +1,4 @@
from app.adapters.system import rust as rust_accelerator
from app.domain.context import configure_tmdb_image_url_builder
from app.domain.media import configure_search_source_provider
from app.domain.meta.customization import configure_customization_provider
@@ -5,7 +6,6 @@ from app.domain.meta.releasegroup import configure_release_groups_provider
from app.domain.meta.runtime import configure_recognition_runtime
from app.domain.meta.words import configure_custom_words_provider
from app.domain.metainfo import clear_rust_parse_options_cache
from app.adapters.system import rust as rust_accelerator
from app.runtime.settings import RuntimeSettingsCompat
settings = RuntimeSettingsCompat()
@@ -17,7 +17,6 @@ from app.runtime.managed_resources import (
configure_managed_resource_runtime,
)
_runtime_lock = threading.RLock()
_managed_resource_runtime: Optional[CapabilityRuntime] = None
+104 -105
View File
@@ -3,7 +3,7 @@ import inspect
import sys
from typing import Callable
from app.adapters.cache.redis import RedisHelper, AsyncRedisHelper
from app.adapters.cache.redis import AsyncRedisHelper, RedisHelper
from app.chain.mediaserver import MediaServerChain
from app.chain.tmdb import TmdbChain
@@ -17,53 +17,57 @@ except ImportError as e:
sys.exit(1)
from app.adapters.system.host import SystemUtils
from app.runtime.config import settings as legacy_settings
from app.runtime.log import logger
from app.runtime.settings import RuntimeSettingsCompat
from app.runtime.config import settings as legacy_settings
from app.runtime.stop import runtime_stop_state
settings = RuntimeSettingsCompat()
from app.runtime.cache import AsyncFileCache, FileCache
from app.runtime.extensions.module_manager import ModuleManager
from app.runtime.extensions.module.dispatcher import ModuleInvocationDispatcher
from app.runtime.extensions.plugin_manager import PluginManager
from app.runtime.events import EventHandlerBinding, EventManager
from app.runtime.execution import run_in_threadpool_to_completion
from app.runtime.observability import record_metric
from app.runtime.state import SystemHelper
from app.runtime.settings import configure_runtime_setting_provider
from app.runtime.thread import ThreadHelper
from app.adapters.external.server import (
MoviePilotServerHelper,
configure_server_application_services,
)
from app.adapters.network.doh import DohHelper
from app.adapters.system.resource import (
ResourceHelper,
configure_resource_version_provider,
)
from app.application.messaging.message import (
MessageHelper,
MessageQueueManager,
stop_message,
from app.adapters.web.security.access import set_superuser_token_payload_provider
from app.api.data import ApiDataPorts, configure_api_data_runtime
from app.application.agentdata import configure_agent_data_ports
from app.application.agenttask import (
AgentTaskExecutionService,
configure_agent_task_execution,
)
from app.application.chain.context import (
ChainRuntimeContext,
configure_chain_runtime_context_provider,
)
from app.application.chain.data import configure_chain_data_ports, get_chain_data_ports
from app.application.chain.durable_events import (
restore_download_added,
restore_transfer_result,
)
from app.application.configuration import (
RuntimeConfiguration,
RuntimeSettingsService,
SystemConfigService,
get_configured_system_config,
TransferRetryConfig,
configure_token_runtime_config,
configure_runtime_configuration,
configure_runtime_settings,
configure_system_config,
configure_token_runtime_config,
configure_transfer_retry_config,
)
from app.startup.composition.configuration import (
build_api_runtime_config,
build_chain_runtime_config,
build_scheduler_runtime_config,
build_token_runtime_config,
get_configured_system_config,
)
from app.application.database import configure_database_governance
from app.application.service import configure_service_directory
from app.application.plugin.runtime import configure_plugin_runtime
from app.application.module import configure_module_runtime
from app.application.history import configure_transfer_history_provider
from app.application.image import configure_wallpaper_providers
from app.application.messaging.agent import (
dispatch_web_agent_message_event,
shutdown_web_agent_background_tasks,
wait_web_agent_background_tasks,
)
from app.application.messaging.chat import (
AgentChatPersistenceService,
AgentChatService,
@@ -71,43 +75,58 @@ from app.application.messaging.chat import (
configure_agent_chat_service,
get_configured_agent_chat_persistence,
)
from app.application.messaging.agent import (
dispatch_web_agent_message_event,
shutdown_web_agent_background_tasks,
wait_web_agent_background_tasks,
from app.application.messaging.message import (
MessageHelper,
MessageQueueManager,
stop_message,
)
from app.application.security.user import configure_user_lookups
from app.application.security.auth import AuthService, configure_auth_service
from app.application.security.passkeys import PasskeyService, configure_passkey_service
from app.application.security.url import close_image_proxy_block_log_coalescer
from app.application.security.userconfig import (
UserConfigurationService,
configure_user_configuration,
)
from app.application.history import configure_transfer_history_provider
from app.application.module import configure_module_runtime
from app.application.outbox import (
OutboxDispatcher,
configure_outbox_dispatcher,
durable_event_topic,
validate_durable_event_handlers,
)
from app.db.adapters.outbox import SqlAlchemyAsyncOutboxStager, SqlAlchemyOutboxRepository
from app.application.site.query import SiteQueryService, configure_site_query_service
from app.application.site.health import SiteHealthService, configure_site_health_service
from app.application.workflow import WorkflowQueryService, configure_workflow_query
from app.application.agentdata import configure_agent_data_ports
from app.application.agenttask import (
AgentTaskExecutionService,
configure_agent_task_execution,
)
from app.api.data import ApiDataPorts, configure_api_data_runtime
from app.application.subscription.write import configure_subscribe_writer
from app.adapters.external.server import (
MoviePilotServerHelper,
configure_server_application_services,
from app.application.plugin.runtime import configure_plugin_runtime
from app.application.security.auth import AuthService, build_superuser_token_payload, configure_auth_service
from app.application.security.passkeys import PasskeyService, configure_passkey_service
from app.application.security.url import close_image_proxy_block_log_coalescer
from app.application.security.user import configure_user_lookups
from app.application.security.userconfig import (
UserConfigurationService,
configure_user_configuration,
)
from app.application.server.report import ServerReportService
from app.application.server.share import ServerSharingService
from app.application.service import configure_service_directory
from app.application.site.health import SiteHealthService, configure_site_health_service
from app.application.site.query import SiteQueryService, configure_site_query_service
from app.application.subscription.write import configure_subscribe_writer
from app.application.workflow import WorkflowQueryService, configure_workflow_query
from app.command import CommandChain
from app.db.adapters.chain import TransactionalChainDurableEventWriter
from app.db.adapters.download import TransactionalDownloadFailureRepository
from app.db.adapters.outbox import SqlAlchemyAsyncOutboxStager, SqlAlchemyOutboxRepository
from app.db.adapters.site import TransactionalSiteRepository
from app.db.adapters.subscription import TransactionalSubscribeWriter
from app.db.adapters.transaction import TransactionalWriteRunner
from app.db.adapters.workflow import TransactionalWorkflowExecutionService
from app.db.oper.agentchat import AgentChatOper
from app.db.oper.agenttask import AgentTaskOper
from app.db.oper.downloadhistory import DownloadHistoryOper
from app.db.oper.mediaserver import MediaServerOper
from app.db.oper.message import MessageOper
from app.db.oper.passkey import PassKeyOper
from app.db.oper.plugindata import PluginDataOper
from app.db.oper.site import SiteOper
from app.db.oper.subscribe import SubscribeOper
from app.db.oper.subscribehistory import SubscribeHistoryOper
from app.db.oper.systemconfig import SystemConfigOper
from app.db.oper.transferhistory import TransferHistoryOper
from app.db.oper.transferpending import TransferPendingOper
from app.db.oper.user import UserOper
from app.db.oper.userconfig import UserConfigOper
from app.db.oper.workflow import WorkflowOper, configure_workflow_legacy_writer
from app.db.session import (
SessionFactory,
async_session_scope,
@@ -115,47 +134,35 @@ from app.db.session import (
get_async_db,
get_db,
)
from app.db.worker import DatabaseWorker
from app.db.uow import (
SqlAlchemyAsyncUnitOfWork,
SqlAlchemyUnitOfWork,
configure_transaction_runners,
)
from app.db.oper.subscribe import SubscribeOper
from app.db.oper.agentchat import AgentChatOper
from app.db.oper.agenttask import AgentTaskOper
from app.db.oper.user import UserOper
from app.db.oper.passkey import PassKeyOper
from app.db.oper.userconfig import UserConfigOper
from app.db.oper.transferhistory import TransferHistoryOper
from app.db.oper.downloadhistory import DownloadHistoryOper
from app.db.oper.transferpending import TransferPendingOper
from app.db.oper.mediaserver import MediaServerOper
from app.db.oper.site import SiteOper
from app.db.oper.message import MessageOper
from app.db.oper.subscribehistory import SubscribeHistoryOper
from app.db.oper.plugindata import PluginDataOper
from app.db.oper.systemconfig import SystemConfigOper
from app.db.oper.workflow import WorkflowOper, configure_workflow_legacy_writer
from app.command import CommandChain
from app.schemas.message import Message
from app.schemas.message import MessageType
from app.db.worker import DatabaseWorker
from app.runtime.cache import AsyncFileCache, FileCache
from app.runtime.events import EventHandlerBinding, EventManager
from app.runtime.execution import run_in_threadpool_to_completion
from app.runtime.extensions.module.dispatcher import ModuleInvocationDispatcher
from app.runtime.extensions.module_manager import ModuleManager
from app.runtime.extensions.plugin_manager import PluginManager
from app.runtime.extensions.service_config import (
ServiceConfigHelper,
configure_service_config_reader,
)
from app.runtime.observability import record_metric
from app.runtime.settings import configure_runtime_setting_provider
from app.runtime.state import SystemHelper
from app.runtime.tasks import get_task_registry
from app.runtime.thread import ThreadHelper
from app.schemas.message import Message, MessageType
from app.schemas.types import EventType, SystemConfigKey
from app.startup.initializers.agent import init_agent
from app.startup.composition.database import build_database_governance
from app.startup.initializers.managed_resources import (
init_managed_resources,
stop_managed_resources,
from app.startup.composition.configuration import (
build_api_runtime_config,
build_chain_runtime_config,
build_scheduler_runtime_config,
build_token_runtime_config,
)
from app.db.adapters.subscription import TransactionalSubscribeWriter
from app.startup.composition.subscription import (
configure_transactional_subscription_scopes,
)
from app.db.adapters.chain import TransactionalChainDurableEventWriter
from app.db.adapters.download import TransactionalDownloadFailureRepository
from app.db.adapters.site import TransactionalSiteRepository
from app.db.adapters.workflow import TransactionalWorkflowExecutionService
from app.db.adapters.transaction import TransactionalWriteRunner
from app.startup.composition.context import (
AgentChatRuntime,
AuthenticationRuntime,
@@ -167,24 +174,15 @@ from app.startup.composition.context import (
SubscriptionRuntime,
WorkflowRuntime,
)
from app.adapters.web.security.access import set_superuser_token_payload_provider
from app.application.security.auth import build_superuser_token_payload
from app.application.image import configure_wallpaper_providers
from app.application.chain.context import (
ChainRuntimeContext,
configure_chain_runtime_context_provider,
from app.startup.composition.database import build_database_governance
from app.startup.composition.subscription import (
configure_transactional_subscription_scopes,
)
from app.application.chain.durable_events import (
restore_download_added,
restore_transfer_result,
from app.startup.initializers.agent import init_agent
from app.startup.initializers.managed_resources import (
init_managed_resources,
stop_managed_resources,
)
from app.application.chain.data import configure_chain_data_ports, get_chain_data_ports
from app.runtime.extensions.service_config import (
ServiceConfigHelper,
configure_service_config_reader,
)
from app.runtime.tasks import get_task_registry
_database_worker: DatabaseWorker | None = None
@@ -252,6 +250,7 @@ def _build_chain_runtime_context() -> ChainRuntimeContext:
configuration=build_chain_runtime_config(settings),
data_ports=get_chain_data_ports(),
durable_event_writer=TransactionalChainDurableEventWriter(SessionFactory),
stop_state=runtime_stop_state,
)
@@ -503,7 +502,7 @@ def stop_frontend():
or not SystemUtils.is_windows():
return
import subprocess
subprocess.Popen(f"taskkill /f /im nginx.exe", shell=True)
subprocess.Popen("taskkill /f /im nginx.exe", shell=True)
def clear_temp():
+29 -29
View File
@@ -1,29 +1,36 @@
from pathlib import Path
from app.application.plugin.routes import register_plugin_api
from app.runtime.compat.diagnostics import (
configure_legacy_import_diagnostics,
scan_plugin_legacy_imports,
)
from app.runtime.compat.resource_imports import scan_plugin_resource_imports
from app.application.plugin.routes import register_plugin_api
from app.runtime.config import global_vars
from app.runtime.settings import RuntimeSettingsCompat
settings = RuntimeSettingsCompat()
from app.runtime.extensions.plugin_manager import (
PluginManager,
configure_plugin_catalog_factory,
configure_plugin_install_reporter,
configure_plugin_legacy_import_services,
configure_plugin_route_refresher,
configure_plugin_resource_import_preparer,
configure_site_auth_level_provider,
from app.adapters.external.market import (
VERSION_BACKWARD_COMPATIBLE_FLAGS,
PluginHelper,
configure_installed_plugins_provider,
)
from app.runtime.execution import run_in_threadpool_to_completion
from app.runtime.extensions.plugin.dependency import PluginDependencyInstallResult
from app.adapters.external.plugin.client import PluginMarketClient
from app.adapters.external.server import MoviePilotServerHelper
from app.adapters.system.host import SystemUtils
from app.adapters.system.plugin.dependency import PluginDependencyInstaller
from app.adapters.system.plugin.manifest import dependency_manifest_status
from app.adapters.system.plugin.package import PluginPackageManager
from app.application.configuration import get_configured_system_config
from app.application.plugin.catalog import PluginCatalogService
from app.application.plugin.data import DeletePluginDataCommand
from app.adapters.external.plugin.client import PluginMarketClient
from app.application.site.sites import SitesHelper # pylint: disable=import-error,no-name-in-module
from app.db.oper.plugindata import PluginDataOper
from app.db.session import SessionFactory
from app.db.uow import SqlAlchemyUnitOfWork
from app.foundation.version import compare_version
from app.runtime.execution import run_in_threadpool_to_completion
from app.runtime.extensions.plugin.dependency import PluginDependencyInstallResult
from app.runtime.extensions.plugin.storage import (
PluginStorage,
configure_plugin_storage,
@@ -32,26 +39,19 @@ from app.runtime.extensions.plugin.system import (
PluginSystemServices,
configure_plugin_system,
)
from app.runtime.managed_resources import acquire_managed_resource
from app.application.site.sites import SitesHelper # pylint: disable=import-error,no-name-in-module
from app.adapters.external.server import MoviePilotServerHelper
from app.adapters.external.market import (
PluginHelper,
VERSION_BACKWARD_COMPATIBLE_FLAGS,
configure_installed_plugins_provider,
from app.runtime.extensions.plugin_manager import (
PluginManager,
configure_plugin_catalog_factory,
configure_plugin_install_reporter,
configure_plugin_legacy_import_services,
configure_plugin_resource_import_preparer,
configure_plugin_route_refresher,
configure_site_auth_level_provider,
)
from app.adapters.system.plugin.dependency import PluginDependencyInstaller
from app.adapters.system.plugin.manifest import dependency_manifest_status
from app.adapters.system.plugin.package import PluginPackageManager
from app.adapters.system.host import SystemUtils
from app.db.oper.plugindata import PluginDataOper
from app.application.configuration import get_configured_system_config
from app.db.session import SessionFactory
from app.db.uow import SqlAlchemyUnitOfWork
from app.runtime.log import logger
from app.foundation.version import compare_version
from app.schemas.plugin import PluginRuntimeStatus
from app.runtime.managed_resources import acquire_managed_resource
from app.schemas.exception import PluginMutationRejectedError
from app.schemas.plugin import PluginRuntimeStatus
from app.schemas.types import SystemConfigKey
+1
View File
@@ -1,5 +1,6 @@
from fastapi import FastAPI
def init_routers(app: FastAPI, api_prefix: str = "/api/v1"):
"""
初始化路由
-1
View File
@@ -1,7 +1,6 @@
from app.application.workflow import configure_workflow_runtime
from app.workflow import WorkFlowManager
# 启动模块是 concrete WorkFlowManager 的唯一宿主装配边界。
configure_workflow_runtime(lambda: WorkFlowManager())
+20 -17
View File
@@ -9,6 +9,7 @@ from typing import Awaitable, Callable
from fastapi import FastAPI
from app.startup.initializers.cache import configure_cache_dependencies
# 缓存装饰器会在业务模块导入时创建后端,必须先完成适配器装配。
configure_cache_dependencies()
# urllib3-future 覆盖 urllib3 命名空间后删除了 format_header_param,导致 telebot 崩溃,需在加载模块前打补丁
@@ -24,23 +25,29 @@ try:
except Exception:
pass
from app.chain.system import SystemChain
from app.application.plugin.lifecycle import plugin_lifecycle
from app.application.plugin.runtime import get_plugin_manager
from app.chain.system import SystemChain
from app.foundation.environment import is_free_threaded_runtime, is_gil_enabled
from app.runtime.config import global_vars
from app.runtime.settings import RuntimeSettingsCompat
from app.foundation.environment import is_free_threaded_runtime, is_gil_enabled
from app.runtime.stop import runtime_stop_state
settings = RuntimeSettingsCompat()
from app.runtime.health import get_application_health
from app.runtime.execution import run_in_threadpool_to_completion
from app.runtime.topology import validate_process_topology
from app.runtime.tasks import TaskRegistry, configure_task_registry
from app.adapters.external.server import MoviePilotServerHelper
from app.adapters.network.http import (
aclose_shared_async_transports,
configure_default_user_agent,
)
from app.db.engine import check_connection_budget, get_engine, get_global_async_engine
from app.runtime.execution import run_in_threadpool_to_completion
from app.runtime.health import get_application_health
from app.runtime.log import LoggerManager, logger
from app.runtime.state import SystemHelper
from app.runtime.log import logger, LoggerManager
from app.startup.initializers.command import init_command, restart_command
from app.runtime.tasks import TaskRegistry, configure_task_registry
from app.runtime.topology import validate_process_topology
from app.startup.initializers.agent import stop_agent
from app.startup.initializers.command import init_command, restart_command
from app.startup.initializers.domain import configure_domain_dependencies
from app.startup.initializers.modules import (
drain_events,
@@ -48,7 +55,7 @@ from app.startup.initializers.modules import (
settle_events,
stop_modules,
)
from app.startup.initializers.monitor import stop_monitor, init_monitor
from app.startup.initializers.monitor import init_monitor, stop_monitor
from app.startup.initializers.plugins import (
configure_plugin_services,
execute_task,
@@ -61,11 +68,10 @@ from app.startup.initializers.plugins import (
)
from app.startup.initializers.routers import init_routers
from app.startup.initializers.scheduler import (
stop_scheduler,
init_scheduler,
init_plugin_scheduler,
init_scheduler,
stop_scheduler,
)
from app.db.engine import check_connection_budget, get_engine, get_global_async_engine
from app.startup.initializers.transfer import (
replay_pending_transfers,
stop_transfer_runtime,
@@ -77,10 +83,6 @@ from app.startup.lifecycle.components import (
LifecycleMode,
lifecycle_manifest,
)
from app.adapters.network.http import (
aclose_shared_async_transports,
configure_default_user_agent,
)
async def init_extra():
@@ -541,7 +543,8 @@ def build_lifecycle_components(app: FastAPI) -> tuple[LifecycleComponent, ...]:
# 停止信号必须先于一切资源释放发出,让工作流、整理等长任务尽早感知停机。
LifecycleComponent(
name="停止信号",
stop=global_vars.stop_system,
# 兼容旧测试与插件;GlobalVar 内部已委托到 StopState。
stop=getattr(global_vars, "stop_system"),
stop_order=4,
stop_timeout_seconds=10,
),