from __future__ import annotations from typing import Any from external_connector.providers.base import ConnectorProvider class CompositeProvider: provider_id = "composite" def __init__(self, providers: list[ConnectorProvider]) -> None: self.providers = providers self._by_kind: dict[str, ConnectorProvider] = {} for provider in providers: for connector in provider.connectors(): self._by_kind[str(connector["kind"])] = provider def connectors(self) -> list[dict[str, Any]]: items: list[dict[str, Any]] = [] for provider in self.providers: items.extend(provider.connectors()) return items def health(self) -> dict[str, Any]: return {"ok": True, "providerId": self.provider_id, "providers": [provider.health() for provider in self.providers]} def start_session(self, payload: dict[str, Any]) -> dict[str, Any]: return self._provider(str(payload["kind"])).start_session(payload) def get_session(self, session_id: str) -> dict[str, Any]: for provider in self.providers: try: return provider.get_session(session_id) except KeyError: continue raise KeyError(session_id) def cancel_session(self, session_id: str) -> None: for provider in self.providers: try: provider.cancel_session(session_id) return None except KeyError: continue raise KeyError(session_id) def logout(self, connection_id: str) -> None: for provider in self.providers: provider.logout(connection_id) return None def send(self, payload: dict[str, Any]) -> dict[str, Any]: return self._provider(str(payload["kind"])).send(payload) def handle_event(self, payload: dict[str, Any]) -> dict[str, Any]: for provider in self.providers: handler = getattr(provider, "handle_event", None) if handler is None: continue try: return dict(handler(payload)) except KeyError: continue raise KeyError("No event provider matched") def _provider(self, kind: str) -> ConnectorProvider: provider = self._by_kind.get(kind) if provider is None: raise KeyError(f"Unsupported connector kind: {kind}") return provider