# app/src/market_data/acquisition/registry.py from __future__ import annotations from src.market_data.acquisition.exceptions import ( InstrumentFeedRegistryError, QuoteFeedRegistryError, ) from src.market_data.acquisition.protocol import ( InstrumentFeedProtocol, QuoteFeedProtocol, ) # Реестр доступных Feed справочника инструментов. class InstrumentFeedRegistry: def __init__(self) -> None: self._feeds: dict[str, InstrumentFeedProtocol] = {} def register( self, source_name: str, feed: InstrumentFeedProtocol, ) -> None: """ Зарегистрировать Instrument Feed для указанного источника. Повторная регистрация того же имени запрещена, чтобы исключить неявную замену production-зависимости. """ normalized_source_name = self._normalize_source_name(source_name) if not isinstance(feed, InstrumentFeedProtocol): raise InstrumentFeedRegistryError( f"Объект для источника '{normalized_source_name}' " "не соответствует InstrumentFeedProtocol." ) if normalized_source_name in self._feeds: raise InstrumentFeedRegistryError( f"Instrument Feed для источника " f"'{normalized_source_name}' уже зарегистрирован." ) self._feeds[normalized_source_name] = feed def get( self, source_name: str, ) -> InstrumentFeedProtocol: """Вернуть зарегистрированный Instrument Feed по имени источника.""" normalized_source_name = self._normalize_source_name(source_name) feed = self._feeds.get(normalized_source_name) if feed is None: raise InstrumentFeedRegistryError( f"Instrument Feed для источника " f"'{normalized_source_name}' не зарегистрирован." ) return feed def _normalize_source_name( self, source_name: str, ) -> str: normalized_source_name = source_name.strip() if not normalized_source_name: raise InstrumentFeedRegistryError( "Имя источника Instrument Feed не должно быть пустым." ) return normalized_source_name # Реестр доступных потоков текущих котировок. class QuoteFeedRegistry: def __init__(self) -> None: self._feeds: dict[str, QuoteFeedProtocol] = {} def register( self, source_name: str, feed: QuoteFeedProtocol, ) -> None: """ Зарегистрировать Quotes Feed для указанного источника. Повторная регистрация того же имени запрещена, чтобы исключить неявную замену production-зависимости. """ normalized_source_name = self._normalize_source_name(source_name) if not isinstance(feed, QuoteFeedProtocol): raise QuoteFeedRegistryError( f"Объект для источника '{normalized_source_name}' " "не соответствует QuoteFeedProtocol." ) if normalized_source_name in self._feeds: raise QuoteFeedRegistryError( f"Quotes Feed для источника " f"'{normalized_source_name}' уже зарегистрирован." ) self._feeds[normalized_source_name] = feed def get( self, source_name: str, ) -> QuoteFeedProtocol: """Вернуть зарегистрированный Quotes Feed по имени источника.""" normalized_source_name = self._normalize_source_name(source_name) feed = self._feeds.get(normalized_source_name) if feed is None: raise QuoteFeedRegistryError( f"Quotes Feed для источника " f"'{normalized_source_name}' не зарегистрирован." ) return feed def _normalize_source_name( self, source_name: str, ) -> str: normalized_source_name = source_name.strip() if not normalized_source_name: raise QuoteFeedRegistryError( "Имя источника Quotes Feed не должно быть пустым." ) return normalized_source_name