21 KiB
Build 059.7 — WebSocket OHLC Adapter
Проект: Dzentra Подсистема: Market Data Acquisition Этап: 059.7 Статус: Completed
Цель
Добавить верхнеуровневый адаптер обработки WebSocket OHLC-событий Dzengi, объединяющий все ранее реализованные стадии обработки в единый конвейер.
Результатом работы адаптера должна стать полностью подготовленная внутренняя модель Dzentra:
CandleCloseEvent
Адаптер становится единственной точкой входа для преобразования WebSocket-сообщения в событие, пригодное для дальнейшей обработки внутри runtime.
Причина изменения
После завершения Build 059.6 система уже содержала полный набор независимых компонентов обработки WebSocket OHLC.
К этому моменту были реализованы:
Schema Validation
↓
Parser
↓
Value Validation
↓
Mapper
Каждый компонент решал строго одну задачу и обладал собственным контрактом ответственности.
Однако использование этих компонентов требовало их последовательного вызова вручную.
Подобный подход приводил к нескольким архитектурным недостаткам:
- отсутствовала единая точка входа;
- порядок выполнения этапов мог быть нарушен;
- различные части системы могли использовать разные последовательности обработки;
- возрастал риск появления дублирующего кода.
Build 059.7 устраняет эти недостатки.
Теперь вся последовательность обработки инкапсулирована внутри одного адаптера.
Реализовано
Изменён файл:
src/market_data/acquisition/adapters/dzengi/websocket.py
Создан файл:
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_adapter.py
Добавлена документация:
docs/migrations/build_059_7.md
Новый адаптер
Добавлен класс:
DzengiWebSocketOhlcAdapter
Основной публичный метод:
map_message()
Назначение метода:
Raw WebSocket document
↓
CandleCloseEvent
Адаптер объединяет все ранее реализованные стадии обработки и предоставляет единый программный интерфейс для остальных компонентов системы.
Конвейер обработки
После завершения Build 059.7 полный pipeline выглядит следующим образом:
Raw WebSocket message
↓
Schema Validation
↓
ValidatedWebSocketOhlcDocument
↓
Parser
↓
DzengiWebSocketOhlcEvent
↓
Value Validation
↓
Mapper
↓
CandleCloseEvent
Все стадии выполняются строго последовательно.
Порядок выполнения не может быть изменён вызывающей стороной.
Последовательность обработки
Внутри метода map_message() выполняются следующие действия.
1. Schema Validation
Выполняется проверка структуры входящего сообщения.
Проверяется наличие обязательных полей транспортного контракта Dzengi:
status
destination
payload
После успешной проверки строится модель:
ValidatedWebSocketOhlcDocument
Ошибки данного этапа приводят к возникновению:
CandleWebSocketSchemaError
2. Parser
Проверенный документ передаётся parser.
Parser преобразует транспортную модель в специализированную внутреннюю модель интеграционного слоя:
DzengiWebSocketOhlcEvent
На этом этапе выполняется преобразование структуры сообщения.
Проверка предметной корректности значений не производится.
Ошибки parser приводят к возникновению:
CandleWebSocketParseError
3. Value Validation
Полученная transport-модель проходит предметную проверку.
Контролируются:
- корректность временной метки;
- допустимость цен;
- допустимость типа свечи;
- непротиворечивость OHLC.
При обнаружении ошибок формируется:
CandleWebSocketValueError
4. Mapper
Последней стадией является mapper.
Он преобразует:
DzengiWebSocketOhlcEvent
в:
CandleCloseEvent
При этом выполняются:
- преобразование timestamp;
- преобразование цен в
Decimal; - установка
source; - перенос
received_at.
После завершения mapper транспортный контракт Dzengi полностью исчезает из дальнейшего pipeline.
Все последующие компоненты работают исключительно с внутренней моделью Dzentra.
Обработка received_at
Метод map_message() принимает дополнительный необязательный параметр:
received_at
Тип параметра:
datetime | None
Возможны два режима работы.
received_at передан
Если вызывающая сторона уже зафиксировала момент получения сообщения, адаптер использует именно это значение.
Никаких дополнительных преобразований времени не выполняется.
Это позволяет сохранить единый момент получения данных на всём протяжении обработки сообщения.
received_at отсутствует
Если параметр не передан, адаптер автоматически создаёт значение:
datetime.now(timezone.utc)
Таким образом каждое успешно обработанное событие всегда содержит корректное время получения.
Использование UTC обеспечивает единый формат времени независимо от локальной временной зоны системы.
Контракт адаптера
Build 059.7 не вводит новых транспортных моделей.
Адаптер использует исключительно ранее реализованные компоненты.
Контракт адаптера можно представить следующим образом:
Input:
Raw WebSocket document
↓
Output:
CandleCloseEvent
При этом адаптер гарантирует строго фиксированную последовательность выполнения всех промежуточных стадий.
Контракт ошибок
Адаптер намеренно не перехватывает исключения нижележащих компонентов.
Каждая стадия обработки продолжает использовать собственный тип ошибки.
Полный контракт выглядит следующим образом:
Transport
↓
CandleTransportError
Schema Validation
↓
CandleWebSocketSchemaError
Parser
↓
CandleWebSocketParseError
Value Validation
↓
CandleWebSocketValueError
Mapper
↓
CandleWebSocketMappingError
При возникновении любой ошибки выполнение pipeline немедленно прекращается.
Исключение передаётся вызывающей стороне без изменения типа.
Такой подход сохраняет независимость отдельных слоёв системы и упрощает диагностику ошибок.
Почему адаптер не перехватывает исключения
Может показаться, что адаптер должен преобразовывать все ошибки в единое исключение.
В Build 059.7 это намеренно не реализовано.
Причины следующие.
Во-первых, каждая стадия уже обладает собственным контрактом.
Во-вторых, сохранение исходного типа исключения позволяет точно определить место возникновения ошибки.
В-третьих, дополнительное оборачивание исключений не несёт новой информации и лишь усложняет диагностику.
Поэтому адаптер выступает исключительно координатором последовательного выполнения pipeline.
Ответственность адаптера
После завершения Build 059.7 ответственность адаптера ограничивается следующими задачами.
Он обязан:
- принять исходное WebSocket-сообщение;
- выполнить полный pipeline обработки;
- при необходимости создать
received_at; - вернуть
CandleCloseEvent.
На этом обязанности адаптера заканчиваются.
Что адаптер НЕ делает
Build 059.7 намеренно не расширяет область ответственности адаптера.
Адаптер не выполняет:
- подключение к WebSocket;
- получение сообщений из сети;
- управление соединением;
- подписку на каналы;
- публикацию событий в runtime;
- REST reconciliation;
- получение объёма свечи;
- построение канонической модели
Candle; - повторную синхронизацию истории;
- обработку разрыва соединения.
Все перечисленные задачи относятся к последующим этапам реализации.
Использование существующих компонентов
Build 059.7 не реализует собственную бизнес-логику обработки свечей.
Вместо этого адаптер объединяет ранее созданные компоненты:
Schema Validator
↓
Parser
↓
Value Validator
↓
Mapper
Таким образом Build 059.7 не дублирует уже реализованную функциональность.
Он только формирует единый программный интерфейс для использования существующего pipeline.
Архитектурное значение
После появления адаптера остальные части системы больше не обязаны знать внутреннее устройство обработки WebSocket OHLC.
Для них существует единственная операция:
Raw WebSocket message
↓
CandleCloseEvent
Вся остальная логика полностью скрыта внутри адаптера.
Это соответствует принципу инкапсуляции и уменьшает связанность между подсистемами.
Unit Tests
Создан файл:
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_adapter.py
Проверяются следующие сценарии.
Построение CandleCloseEvent
Проверяется полный pipeline обработки.
Исходное WebSocket-сообщение должно успешно пройти:
Schema Validation
↓
Parser
↓
Value Validation
↓
Mapper
↓
CandleCloseEvent
Проверяется корректность всех основных полей:
- symbol;
- interval;
- candle_type;
- open_price;
- high_price;
- low_price;
- close_price;
- source;
- received_at.
Автоматическая установка received_at
Если вызывающая сторона не передала параметр:
received_at
адаптер обязан автоматически установить текущее UTC-время.
Тест подтверждает наличие значения и корректность его типа.
Сохранение ошибок Value Validation
Если входное сообщение содержит недопустимые значения, адаптер не должен скрывать возникшее исключение.
Проверяется, что наружу передаётся:
CandleWebSocketValueError
без изменения типа ошибки.
Проверка полного pipeline
Отдельный тест подтверждает, что адаптер действительно выполняет все стадии обработки.
В результате вызывающая сторона получает уже полностью построенный объект:
CandleCloseEvent
без необходимости самостоятельно вызывать parser, validator и mapper.
Всего выполнено:
4 tests
Проверка синтаксиса
Выполнена команда:
python -m compileall \
src/market_data/acquisition/adapters/dzengi/websocket.py \
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_adapter.py
Результат:
успешно
Целевые тесты
Выполнена команда:
python -m pytest -q \
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_adapter.py
Результат:
4 passed
Регрессия адаптеров
Выполнена команда:
python -m pytest -q \
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_quote_adapter.py \
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_adapter.py
Результат:
6 passed
Регрессия полного WebSocket pipeline
Выполнена команда:
python -m pytest -q \
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_quote_parser.py \
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_quote_mapper.py \
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_quote_adapter.py \
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_parser.py \
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_mapper.py \
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_adapter.py
Результат:
65 passed
Проверка форматирования
Выполнена команда:
git diff --check
Ошибок форматирования не обнаружено.
Изменённые файлы
src/market_data/acquisition/adapters/dzengi/websocket.py
Создан файл:
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_adapter.py
Документация:
docs/migrations/build_059_7.md
Совместимость
Build 059.7 полностью обратно совместим.
Не изменены:
- REST Candles Feed;
- REST Candle mapper;
- Quote parser;
- Quote mapper;
- WebSocket Quote Adapter;
- ExchangeService;
- runtime;
- Trading;
- Market Analysis;
- каноническая модель
Candle.
Новый адаптер пока не встроен в существующий runtime и не влияет на работу действующего торгового бота.
Архитектурное значение
Build 059.7 завершает формирование верхнего уровня обработки WebSocket OHLC.
После предыдущих этапов система уже обладала всеми необходимыми компонентами:
Schema Validation
Parser
Value Validation
Mapper
Теперь появился единый компонент, объединяющий их в законченный конвейер.
После Build 059.7 архитектура обработки выглядит следующим образом:
Raw WebSocket Message
│
▼
WebSocket OHLC Adapter
│
▼
Schema Validation
│
▼
Parser
│
▼
Value Validation
│
▼
Mapper
│
▼
CandleCloseEvent
Таким образом внешний код взаимодействует только с адаптером.
Внутренние детали обработки полностью инкапсулированы.
Это уменьшает связанность компонентов и соответствует архитектурным принципам Dzentra.
Ограничения этапа
Build 059.7 намеренно не реализует:
- подписку на WebSocket;
- управление соединением;
- автоматическое получение сообщений;
- публикацию событий в runtime;
- REST reconciliation;
- получение объёма свечи;
- построение канонической модели
Candle; - проверку соответствия REST и WebSocket данных;
- восстановление после разрыва соединения;
- повторную синхронизацию истории.
Все перечисленные задачи относятся к следующим этапам серии Build 059.
Итог
Build 059.7 добавляет полноценный верхнеуровневый адаптер обработки WebSocket OHLC.
В результате система получила:
- единую точку входа для обработки WebSocket OHLC;
- полностью инкапсулированный pipeline обработки;
- автоматическое создание
received_at; - единый интерфейс получения
CandleCloseEvent; - сохранение независимых контрактов ошибок всех стадий обработки;
- полный набор unit-тестов и успешное прохождение регрессии.
После завершения Build 059.7 конвейер обработки WebSocket OHLC полностью готов к интеграции с механизмом подписки и дальнейшей публикации событий внутри runtime.
Следующий этап
Build 059.8 — Unified Adapter
На этом этапе будет реализован единый адаптер верхнего уровня, способный принимать различные типы сообщений Dzengi WebSocket, определять их тип и направлять в соответствующий специализированный адаптер, формируя унифицированную точку входа для всего WebSocket-потока.