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