ForcePilot/backend/package/yuxi/channels/infrastructure/dependency_injection.py

92 lines
3.4 KiB
Python
Raw Normal View History

"""framework/bootstrap/dependency_injection.py依赖注入容器。
本模块是编排层的依赖注入装配点负责管理 framework 层组件的单例注册
与解析借鉴 external_systems ``infrastructure/container.py`` 组合根
概念但采用可变注册表形态以支持启动期分散注册请求期按需解析
设计原则
- framework 层组件注册中心EventBus熔断器等为应用级单例跨请求复用
- 请求级组件被驱动适配器管道用例服务由各自 factory 按请求创建不进入容器
``create_driven_adapters(db, 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]