From 7ae6aec24459668c4b628bc1e1614c2b0813676c Mon Sep 17 00:00:00 2001 From: Marco Melloni <98281551+marcomelloni@users.noreply.github.com> Date: Wed, 16 Jul 2025 16:19:46 +0200 Subject: [PATCH 1/2] Add in-memory protocol config option --- simulation_bridge/config/config.yaml.template | 1 + .../src/core/bridge_orchestrator.py | 3 +- .../inmemory/inmemory_adapter.py | 41 ------------------- .../protocol_adapters/inmemory_signal.json | 21 ++++++++++ simulation_bridge/src/utils/config_loader.py | 23 ++++++++--- simulation_bridge/src/utils/config_manager.py | 4 +- .../test/integration/test_integration.py | 22 +++++----- 7 files changed, 55 insertions(+), 60 deletions(-) create mode 100644 simulation_bridge/src/protocol_adapters/inmemory_signal.json diff --git a/simulation_bridge/config/config.yaml.template b/simulation_bridge/config/config.yaml.template index 83031cc8..cd379ac3 100644 --- a/simulation_bridge/config/config.yaml.template +++ b/simulation_bridge/config/config.yaml.template @@ -1,5 +1,6 @@ simulation_bridge: bridge_id: simulation_bridge + in_memory_mode: false rabbitmq: host: localhost diff --git a/simulation_bridge/src/core/bridge_orchestrator.py b/simulation_bridge/src/core/bridge_orchestrator.py index 6406df16..b698a2bd 100644 --- a/simulation_bridge/src/core/bridge_orchestrator.py +++ b/simulation_bridge/src/core/bridge_orchestrator.py @@ -41,7 +41,8 @@ def __init__(self, config_path: str = None): self.adapters = {} self._running = False - self.protocol_config = load_protocol_config() + self.protocol_config = load_protocol_config(self.config_manager.config_path) + SignalManager.PROTOCOL_CONFIG = self.protocol_config self.adapter_classes = self._import_adapter_classes() def setup_interfaces(self): diff --git a/simulation_bridge/src/protocol_adapters/inmemory/inmemory_adapter.py b/simulation_bridge/src/protocol_adapters/inmemory/inmemory_adapter.py index 5337017f..b4ed7e8d 100644 --- a/simulation_bridge/src/protocol_adapters/inmemory/inmemory_adapter.py +++ b/simulation_bridge/src/protocol_adapters/inmemory/inmemory_adapter.py @@ -84,41 +84,6 @@ def _handle_message(self, message: Dict[str, Any]) -> None: # pylint: disable=u pass -class DummyAdapter(ProtocolAdapter): - """Neutral adapter for MQTT and REST protocols.""" - - def __init__(self, config_manager: ConfigManager | None = None): - super().__init__(config_manager or ConfigManager(None)) - - def _get_config(self) -> Dict[str, Any]: - return {} - - def start(self) -> None: - logger.debug("DummyAdapter started (no-op)") - self._running = True - - def stop(self) -> None: - logger.debug("DummyAdapter stopped (no-op)") - self._running = False - - def _handle_message(self, message: Dict[str, Any]) -> None: # noqa: D401 - # This method is intentionally empty as DummyAdapter serves as a null object - # to prevent errors when MQTT/REST protocols are not used but signals expect - # these adapters to be registered - pass - - def publish_result_message_mqtt(self, *_, **__) -> None: - # This method is intentionally empty as DummyAdapter serves as a null object - # to prevent errors when MQTT/REST protocols are not used but signals expect - # these adapters to be registered - pass - - def publish_result_message_rest(self, *_, **__) -> None: - # This method is intentionally empty as DummyAdapter serves as a null object - # to prevent errors when MQTT/REST protocols are not used but signals expect - # these adapters to be registered - pass - class SimulationBridge: """Run simulations using the in-memory protocol adapter.""" @@ -140,12 +105,6 @@ def __init__(self, config_path: str | None = None) -> None: SignalManager.register_adapter_instance( "rabbitmq", self.rabbitmq_adapter) - # Required to satisfy signals expecting these adapters. - # Acts as a "null object" to avoid errors when MQTT/REST are unused. - dummy = DummyAdapter() - SignalManager.register_adapter_instance("mqtt", dummy) - SignalManager.register_adapter_instance("rest", dummy) - SignalManager.connect_all_signals() self.inmemory_adapter.start() diff --git a/simulation_bridge/src/protocol_adapters/inmemory_signal.json b/simulation_bridge/src/protocol_adapters/inmemory_signal.json new file mode 100644 index 00000000..d04380e3 --- /dev/null +++ b/simulation_bridge/src/protocol_adapters/inmemory_signal.json @@ -0,0 +1,21 @@ +{ + "protocols": { + "rabbitmq": { + "enabled": true, + "signals": { + "message_received_input_rabbitmq": "BridgeCore.handle_input_message", + "message_received_result_rabbitmq": "BridgeCore.handle_result_rabbitmq_message", + "message_received_result_unknown": "BridgeCore.handle_result_unknown_message" + }, + "class": ".rabbitmq.rabbitmq_adapter.RabbitMQAdapter" + }, + "inmemory": { + "enabled": true, + "signals": { + "message_received_input_inmemory": "BridgeCore.handle_input_message", + "message_received_result_inmemory": "InMemoryAdapter._handle_result" + }, + "class": ".inmemory.inmemory_adapter.InMemoryAdapter" + } + } +} diff --git a/simulation_bridge/src/utils/config_loader.py b/simulation_bridge/src/utils/config_loader.py index 6c11ec36..08441531 100644 --- a/simulation_bridge/src/utils/config_loader.py +++ b/simulation_bridge/src/utils/config_loader.py @@ -88,11 +88,22 @@ def _substitute_env_vars( return config -def load_protocol_config() -> Dict[str, list]: - """ - Load the protocol configuration from a JSON file. +def load_protocol_config(config_path: Optional[Union[str, Path]] = None) -> Dict[str, list]: + """Load the protocol configuration based on in-memory mode. + + If the provided configuration file (or the default one) contains + ``in_memory_mode: true`` under ``simulation_bridge``, the reduced + ``inmemory_signal.json`` file will be loaded instead of the full + ``adapters_signal.json``. """ - config_file = Path(__file__).parent.parent / \ - "protocol_adapters/adapters_signal.json" - with open(config_file, 'r', encoding='utf-8') as f: + cfg_path = Path(config_path) if config_path else Path(__file__).parent.parent.parent.parent / "config.yaml" + in_memory = False + try: + cfg = load_config(str(cfg_path)) + in_memory = cfg.get("simulation_bridge", {}).get("in_memory_mode", False) + except Exception: # noqa: BLE001 + logger.debug("Configuration not found or invalid, using defaults") + json_name = "inmemory_signal.json" if in_memory else "adapters_signal.json" + config_file = Path(__file__).parent.parent / f"protocol_adapters/{json_name}" + with open(config_file, "r", encoding="utf-8") as f: return json.load(f)["protocols"] diff --git a/simulation_bridge/src/utils/config_manager.py b/simulation_bridge/src/utils/config_manager.py index d75e86bf..e42428f2 100644 --- a/simulation_bridge/src/utils/config_manager.py +++ b/simulation_bridge/src/utils/config_manager.py @@ -113,6 +113,7 @@ class PerformanceConfig(BaseModel): class SimulationBridgeConfig(BaseModel): """Configuration for simulation bridge.""" bridge_id: str + in_memory_mode: bool = False class Config(BaseModel): @@ -237,7 +238,8 @@ def get_default_config(self) -> Dict[str, Any]: """Get default configuration as dictionary.""" return Config( simulation_bridge=SimulationBridgeConfig( - bridge_id="simulation_bridge"), + bridge_id="simulation_bridge", + in_memory_mode=False), rabbitmq=RabbitMQConfig( host="localhost", port=5672, diff --git a/simulation_bridge/test/integration/test_integration.py b/simulation_bridge/test/integration/test_integration.py index 5032f1dd..93e31d15 100644 --- a/simulation_bridge/test/integration/test_integration.py +++ b/simulation_bridge/test/integration/test_integration.py @@ -323,7 +323,7 @@ def fake_ensure_certificates(**kwargs): # pylint: disable=unused-argument MagicMock()) monkeypatch.setattr( "simulation_bridge.src.core.bridge_orchestrator.load_protocol_config", - lambda: {}) + lambda *a, **k: {}) monkeypatch.setattr( "simulation_bridge.src.core.bridge_orchestrator.BridgeOrchestrator._import_adapter_classes", lambda self: {}) @@ -344,7 +344,7 @@ def fake_ensure_certificates(**kwargs): # pylint: disable=unused-argument MagicMock()) monkeypatch.setattr( "simulation_bridge.src.core.bridge_orchestrator.load_protocol_config", - lambda: {}) + lambda *a, **k: {}) monkeypatch.setattr( "simulation_bridge.src.core.bridge_orchestrator.BridgeOrchestrator._import_adapter_classes", lambda self: {}) @@ -367,7 +367,7 @@ def fake_ensure_certificates(**kwargs): MagicMock()) monkeypatch.setattr( "simulation_bridge.src.core.bridge_orchestrator.load_protocol_config", - lambda: {}) + lambda *a, **k: {}) monkeypatch.setattr( "simulation_bridge.src.core.bridge_orchestrator.BridgeOrchestrator._import_adapter_classes", lambda self: {}) @@ -385,7 +385,7 @@ def test_bridge_orchestrator_start_and_stop(monkeypatch, mock_config_manager): lambda *a, **k: mock_config_manager) monkeypatch.setattr( "simulation_bridge.src.core.bridge_orchestrator.load_protocol_config", - lambda: {}) + lambda *a, **k: {}) monkeypatch.setattr( "simulation_bridge.src.core.bridge_orchestrator.BridgeOrchestrator._import_adapter_classes", lambda self: {}) @@ -412,7 +412,7 @@ def test_bridge_orchestrator_logs_bridge_id(monkeypatch, caplog): 'rabbitmq': {}})) monkeypatch.setattr( "simulation_bridge.src.core.bridge_orchestrator.load_protocol_config", - lambda: {}) + lambda *a, **k: {}) monkeypatch.setattr( "simulation_bridge.src.core.bridge_orchestrator.BridgeOrchestrator._import_adapter_classes", lambda self: {}) @@ -507,7 +507,7 @@ def test_bridge_orchestrator_logs_error_on_exception(monkeypatch, caplog): 'rabbitmq': {}})) monkeypatch.setattr( "simulation_bridge.src.core.bridge_orchestrator.load_protocol_config", - lambda: {}) + lambda *a, **k: {}) monkeypatch.setattr( "simulation_bridge.src.core.bridge_orchestrator.BridgeOrchestrator._import_adapter_classes", lambda self: {}) @@ -550,7 +550,7 @@ def mock_ensure_certificates(**kwargs): 'rabbitmq': {}})) monkeypatch.setattr( "simulation_bridge.src.core.bridge_orchestrator.load_protocol_config", - lambda: {}) + lambda *a, **k: {}) monkeypatch.setattr( "simulation_bridge.src.core.bridge_orchestrator.BridgeOrchestrator._import_adapter_classes", lambda self: {}) @@ -622,7 +622,7 @@ def mock_ensure_certificates(**kwargs): 'rabbitmq': {}})) monkeypatch.setattr( "simulation_bridge.src.core.bridge_orchestrator.load_protocol_config", - lambda: {}) + lambda *a, **k: {}) monkeypatch.setattr( "simulation_bridge.src.core.bridge_orchestrator.BridgeOrchestrator._import_adapter_classes", lambda self: {}) @@ -657,7 +657,7 @@ def mock_ensure_certificates(**kwargs): 'rabbitmq': {}})) monkeypatch.setattr( "simulation_bridge.src.core.bridge_orchestrator.load_protocol_config", - lambda: {}) + lambda *a, **k: {}) monkeypatch.setattr( "simulation_bridge.src.core.bridge_orchestrator.BridgeOrchestrator._import_adapter_classes", lambda self: {}) @@ -698,7 +698,7 @@ def mock_ensure_certificates(**kwargs): 'rabbitmq': {}})) monkeypatch.setattr( "simulation_bridge.src.core.bridge_orchestrator.load_protocol_config", - lambda: {}) + lambda *a, **k: {}) monkeypatch.setattr( "simulation_bridge.src.core.bridge_orchestrator.BridgeOrchestrator._import_adapter_classes", lambda self: {}) @@ -729,7 +729,7 @@ def mock_ensure_certificates(**kwargs): 'rabbitmq': {}})) monkeypatch.setattr( "simulation_bridge.src.core.bridge_orchestrator.load_protocol_config", - lambda: {}) + lambda *a, **k: {}) monkeypatch.setattr( "simulation_bridge.src.core.bridge_orchestrator.BridgeOrchestrator._import_adapter_classes", lambda self: {}) From 994f249f90fc65c9dc6d22aaacb5f92ac2f73c93 Mon Sep 17 00:00:00 2001 From: Marco Melloni <98281551+marcomelloni@users.noreply.github.com> Date: Wed, 16 Jul 2025 17:07:08 +0200 Subject: [PATCH 2/2] Fix in-memory protocol loading --- .../src/protocol_adapters/inmemory/inmemory_adapter.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/simulation_bridge/src/protocol_adapters/inmemory/inmemory_adapter.py b/simulation_bridge/src/protocol_adapters/inmemory/inmemory_adapter.py index b4ed7e8d..bde3f2cc 100644 --- a/simulation_bridge/src/protocol_adapters/inmemory/inmemory_adapter.py +++ b/simulation_bridge/src/protocol_adapters/inmemory/inmemory_adapter.py @@ -7,6 +7,7 @@ from ...utils.logger import get_logger from ..base.protocol_adapter import ProtocolAdapter from ...utils.signal_manager import SignalManager +from ...utils.config_loader import load_protocol_config from ...core.bridge_core import BridgeCore from ..rabbitmq.rabbitmq_adapter import RabbitMQAdapter @@ -90,6 +91,8 @@ class SimulationBridge: def __init__(self, config_path: str | None = None) -> None: self.config_manager = ConfigManager(config_path) + SignalManager.PROTOCOL_CONFIG = load_protocol_config( + self.config_manager.config_path) self.inmemory_adapter = InMemoryAdapter(self.config_manager) self.rabbitmq_adapter = RabbitMQAdapter(self.config_manager)