build 059.8: add unified websocket adapter

This commit is contained in:
2026-07-17 13:30:32 +03:00
parent 20a70df1f0
commit e5a4efa5d1
4 changed files with 690 additions and 0 deletions

View File

@@ -12,6 +12,9 @@ from src.market_data.acquisition.adapters.dzengi.parser import (
parse_dzengi_websocket_ohlc,
parse_dzengi_websocket_quote,
)
from src.market_data.acquisition.exceptions import (
WebSocketMessageRoutingError,
)
from src.market_data.acquisition.models.candle_close import CandleCloseEvent
from src.market_data.acquisition.models.quote import Quote
from src.market_data.acquisition.validation.schema import (
@@ -58,4 +61,44 @@ class DzengiWebSocketOhlcAdapter:
return map_dzengi_websocket_ohlc_to_candle_close_event(
event,
received_at=received_at or datetime.now(timezone.utc),
)
# Определяет тип декодированного сообщения Dzengi WebSocket
# и передаёт его соответствующему специализированному адаптеру.
class DzengiUnifiedWebSocketAdapter:
def __init__(
self,
*,
quote_adapter: DzengiWebSocketQuoteAdapter | None = None,
ohlc_adapter: DzengiWebSocketOhlcAdapter | None = None,
) -> None:
self._quote_adapter = quote_adapter or DzengiWebSocketQuoteAdapter()
self._ohlc_adapter = ohlc_adapter or DzengiWebSocketOhlcAdapter()
def map_message(
self,
document: object,
*,
received_at: datetime | None = None,
) -> Quote | CandleCloseEvent:
if not isinstance(document, dict):
raise WebSocketMessageRoutingError(
"Сообщение Dzengi WebSocket должно быть объектом."
)
if document.get("destination") == "ohlc.event":
return self._ohlc_adapter.map_message(
document,
received_at=received_at,
)
if "Payload" in document:
return self._quote_adapter.map_message(
document,
received_at=received_at,
)
raise WebSocketMessageRoutingError(
"Не удалось определить тип сообщения Dzengi WebSocket."
)

View File

@@ -117,3 +117,9 @@ class CandleMappingError(MarketDataAcquisitionError):
# Ошибка регистрации или получения Candles Feed.
class CandleFeedRegistryError(MarketDataAcquisitionError):
pass
# Ошибка определения типа входящего WebSocket-сообщения
# и выбора специализированного адаптера.
class WebSocketMessageRoutingError(MarketDataAcquisitionError):
pass