ForcePilot/backend/package/yuxi/channels/infrastructure/dependency_injection.py
Kris bb1934023e refactor: 完成会话持久化与事务机制重构,清理冗余代码
本次提交是一次大型架构重构,核心变更包括:
1. 调整持久化适配器为无状态实现,通过session_factory按需获取会话
2. 重构事务共享与透传机制,统一使用_session_scope管理会话生命周期
3. 移除OutboxEntry聚合根内的版本自增逻辑,由持久化层统一管理
4. 优化微信插件会话类型枚举与配置对齐
5. 简化出站管道阶段依赖注入与流程逻辑
6. 删除健康检查自动释放会话的冗余代码
7. 重构多个定时任务处理器,移除显式会话工厂创建逻辑
8. 修复会话延迟加载异常问题,新增时区转换工具函数
2026-07-10 04:10:33 +08:00

92 lines
3.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""framework/bootstrap/dependency_injection.py依赖注入容器。
本模块是编排层的依赖注入装配点,负责管理 framework 层组件的单例注册
与解析。借鉴 external_systems 的 ``infrastructure/container.py`` 组合根
概念,但采用可变注册表形态以支持启动期分散注册、请求期按需解析。
设计原则:
- framework 层组件注册中心、EventBus、熔断器等为应用级单例跨请求复用
- 请求级组件(被驱动适配器、管道、用例服务)由各自 factory 按请求创建,不进入容器
(如 ``create_driven_adapters(db, session_factory, outbox_config, redis_client, arq_pool, execution_port)``
与 ``InboundPipeline.create()`` / ``ControlPlanePipeline.create()`` /
``OutboundPipeline.create()``
- 容器仅负责应用级单例的注册与解析,保持职责单一
- 线程安全:所有读写操作通过 ``threading.Lock`` 串行化
"""
from __future__ import annotations
import threading
from typing import Any
from yuxi.channels.contract.errors import InternalError
__all__ = [
"DependencyInjectionContainer",
]
class DependencyInjectionContainer:
"""依赖注入容器。
管理 framework 层组件的单例注册,提供统一的依赖解析入口。
注册形态仅支持单例:由调用方在启动期直接传入已构造实例,
``resolve`` 时原样返回。未注册的接口解析失败抛出 ``InternalError``
因为这属于装配期编程错误(漏注册),而非客户端请求的资源不存在。
线程安全:所有注册与解析操作通过同一把 ``threading.Lock`` 串行化,
保证并发场景下注册表的读写一致性。
典型用法::
container = DependencyInjectionContainer()
container.registerSingleton(EventBus, InMemoryEventBus())
container.registerSingleton(PluginRegistry, PluginRegistry())
event_bus = container.resolve(EventBus)
plugin_registry = container.resolve(PluginRegistry)
"""
def __init__(self) -> None:
"""初始化依赖注入容器。
创建空的单例注册表与互斥锁。
"""
self._singletons: dict[type, Any] = {}
self._lock = threading.Lock()
def registerSingleton(self, interface: type, instance: Any) -> None:
"""注册单例。
将已构造的实例绑定到指定接口类型,后续 ``resolve`` 直接返回该实例。
若同一接口已注册,则覆盖原有绑定。
Args:
interface: 接口类型(通常为 Protocol 或抽象基类),作为解析键。
instance: 已构造的实例,将作为单例原样返回。
"""
with self._lock:
self._singletons[interface] = instance
def resolve(self, interface: type) -> Any:
"""解析依赖。
返回绑定到该接口的单例实例。若接口未注册,抛出 ``InternalError``。
Args:
interface: 接口类型(通常为 Protocol 或抽象基类),作为解析键。
Returns:
绑定到该接口的单例实例。
Raises:
InternalError: 该接口未注册单例(装配期漏注册,属编程错误)。
"""
with self._lock:
if interface not in self._singletons:
raise InternalError(
message=f"Dependency not registered: {interface.__name__}",
)
return self._singletons[interface]