odoo_mqtt/iot_bridge/dependencies.py
matthias.lotz a4ea77e6b3 feat(phase2.4): add dependency injection container and factory wiring
Implemented Phase 2.4 (Dependency Injection Pattern):

- Added new dependencies module with DI container and runtime context
  - RuntimeContainer for injectable factories
  - RuntimeContext for resolved runtime objects
  - create_service_manager() factory
  - build_runtime_context() composition root
- Refactored main.py to use dependency container wiring
  - Main orchestration now resolves runtime via DI factories
  - Reduced direct constructor coupling in entrypoint
- Added unit tests for DI behavior with mocked dependencies
  - Verifies factory injection for service manager creation
  - Verifies runtime composition uses injected callables
- Updated optimization plan checkboxes for Phase 2.4

Validation:
- py_compile passed for new/changed files
- tests/unit/test_dependencies.py passed
- regression test test_event_queue::test_enqueue passed

Notes:
- Keeps existing runtime behavior unchanged
- Establishes clear composition root for future testability improvements
2026-02-18 23:17:22 +01:00

57 lines
1.8 KiB
Python

"""Dependency injection helpers for IoT Bridge runtime wiring."""
from dataclasses import dataclass
from typing import Callable
from core.bootstrap import BootstrapConfig, bootstrap, get_mqtt_config
from core.service_manager import ServiceManager
@dataclass(frozen=True)
class RuntimeContainer:
"""Container for runtime dependencies and factory callables."""
bootstrap_factory: Callable[[], BootstrapConfig] = bootstrap
mqtt_config_factory: Callable[[object], object] = get_mqtt_config
service_manager_factory: Callable[..., ServiceManager] = ServiceManager
@dataclass(frozen=True)
class RuntimeContext:
"""Resolved runtime objects used by main orchestration."""
boot_config: BootstrapConfig
service_manager: ServiceManager
mqtt_config: object
def create_service_manager(
boot_config: BootstrapConfig,
service_manager_factory: Callable[..., ServiceManager] = ServiceManager,
) -> ServiceManager:
"""Create service manager via injectable factory."""
return service_manager_factory(
config=boot_config.config,
logger=boot_config.logger,
bridge_port=boot_config.bridge_port,
bridge_token=boot_config.bridge_token,
)
def build_runtime_context(container: RuntimeContainer | None = None) -> RuntimeContext:
"""Resolve runtime context from dependency container."""
runtime_container = container or RuntimeContainer()
boot_config = runtime_container.bootstrap_factory()
service_manager = create_service_manager(
boot_config=boot_config,
service_manager_factory=runtime_container.service_manager_factory,
)
mqtt_config = runtime_container.mqtt_config_factory(boot_config.config)
return RuntimeContext(
boot_config=boot_config,
service_manager=service_manager,
mqtt_config=mqtt_config,
)