# Build 060.15 — Unified WebSocket Routing **Engineering Migration Report** --- # Контроль документа | Свойство | Значение | |----------|----------| | Build | 060.15 | | Название | Unified WebSocket Routing | | Статус | Completed | | Проект | Dzentra | | Подсистема | Market Data Acquisition | | Компонент | Trades Feed | | Версия | 1.0 | --- # Цель Build После завершения Build 060.14 система получила полностью реализованный уровень **WebSocket Trade Adapter**. К этому моменту Pipeline обработки WebSocket Trade уже гарантировал: - корректность структуры транспортного документа; - успешное построение транспортной модели; - корректность всех обязательных значений; - успешное преобразование транспортной модели в каноническую модель предметной области; - наличие единой точки входа транспортного Pipeline. Однако полученный Adapter ещё не был встроен в существующую инфраструктуру получения WebSocket-сообщений. Архитектура Dzentra уже содержала единый компонент маршрутизации входящих сообщений — ```text DzengiUnifiedWebSocketAdapter ``` который определял тип входящего сообщения и направлял его в соответствующий специализированный Adapter. До начала Build поддерживались только два типа сообщений: ```text Quote ``` и ```text OHLC ``` Поддержка сообщений ```text Trade ``` отсутствовала. В результате Trade Pipeline существовал как полностью реализованный, но оставался недоступным для общего механизма маршрутизации WebSocket. Основная задача Build заключается в расширении существующего Unified WebSocket Routing без изменения ранее реализованной архитектуры. После завершения Build компонент ```text DzengiUnifiedWebSocketAdapter ``` должен уметь автоматически определять сообщения ```text internal.trade ``` и передавать их в специализированный Adapter обработки Trade. При этом Build не затрагивает: - WebSocket Runtime; - транспортный протокол; - Schema Validation; - Parser; - Value Validation; - Mapper; - внутреннюю архитектуру Trade Adapter; - Trades Feed. --- # Предпосылки К началу Build архитектура WebSocket уже содержала единый механизм маршрутизации сообщений. Он обеспечивал разделение различных типов транспортных событий между специализированными Adapter. Конвейер обработки выглядел следующим образом. ```text Raw WebSocket Message │ ▼ DzengiUnifiedWebSocketAdapter │ ├────────► Quote Adapter │ └────────► OHLC Adapter ``` Каждый специализированный Adapter полностью инкапсулировал собственный транспортный Pipeline. После завершения Build 060.14 аналогичный Pipeline уже существовал и для Trade. ```text ValidatedWebSocketTradeDocument │ ▼ WebSocket Trade Adapter │ ├────────► Parser │ ├────────► Value Validation │ ├────────► Mapper │ ▼ Trade ``` Однако данный Adapter не был подключён к общему механизму маршрутизации. В результате система не могла автоматически обрабатывать входящие сообщения о сделках, несмотря на полностью реализованный транспортный Pipeline. Таким образом архитектура Unified WebSocket Routing оставалась незавершённой. --- # Архитектурное основание Одним из фундаментальных принципов архитектуры Dzentra является централизованная маршрутизация транспортных сообщений. Определение типа входящего сообщения должно происходить исключительно в одном месте системы. Именно эту задачу выполняет ```text DzengiUnifiedWebSocketAdapter ``` После определения типа события дальнейшая обработка полностью передаётся специализированному Adapter соответствующего типа данных. Полная схема обработки WebSocket-сообщений принимает следующий вид. ```text Raw WebSocket Message │ ▼ Unified Routing │ ├────────► Quote Adapter │ ├────────► OHLC Adapter │ └────────► Trade Adapter ``` Каждый специализированный Adapter полностью инкапсулирует собственный транспортный Pipeline. Unified Router принципиально **не выполняет**: - Schema Validation; - Parser; - Value Validation; - Mapper; - бизнес-логику; - принятие торговых решений; - обработку Runtime. Его единственная ответственность — определить тип входящего сообщения и передать его соответствующему Adapter. Подобное разделение ответственности обеспечивает: - единое место маршрутизации всех WebSocket-событий; - независимое развитие отдельных Pipeline; - повторное использование существующих Adapter; - отсутствие дублирования логики определения типа сообщений. --- # Результаты архитектурного аудита Перед реализацией Build был выполнен аудит существующей архитектуры WebSocket Routing. В ходе анализа подтверждено наличие полностью реализованного компонента ```text DzengiUnifiedWebSocketAdapter ``` который уже обеспечивал маршрутизацию сообщений Quote и OHLC. Также был выполнен аудит транспортного уровня Runtime. Анализ подтвердил, что ```text runtime/websocket_protocol.py ``` не содержит логики определения типов сообщений и не должен выполнять: - Schema Validation; - Parser; - Value Validation; - Mapper; - транспортную маршрутизацию. Данный принцип уже закреплён архитектурой подсистемы Market Data Acquisition. Кроме того, аудит подтвердил полную готовность WebSocket Trade Adapter, реализованного в Build 060.14. Таким образом единственным отсутствующим элементом архитектуры являлось подключение нового Adapter к существующему механизму Unified Routing. --- # Архитектурное решение По результатам проведённого аудита было принято решение сохранить существующую архитектуру маршрутизации без изменения её принципов. В компонент ```text DzengiUnifiedWebSocketAdapter ``` добавлена поддержка нового специализированного Adapter. После определения значения ```text destination = "internal.trade" ``` маршрутизатор передаёт документ в ```text DzengiWebSocketTradeAdapter ``` который выполняет полный транспортный Pipeline обработки и возвращает готовую каноническую модель ```text Trade ``` После завершения обработки вызывающая сторона получает результат в виде одной из трёх канонических моделей предметной области. ```text Quote CandleCloseEvent Trade ``` Конвейер обработки WebSocket принимает следующий вид. ```text Raw WebSocket Message │ ▼ DzengiUnifiedWebSocketAdapter │ ├────────► Quote Adapter │ │ │ ▼ │ Quote │ ├────────► OHLC Adapter │ │ │ ▼ │ CandleCloseEvent │ └────────► Trade Adapter │ ▼ Trade ``` Build 060.15 не изменяет архитектуру Runtime, не затрагивает ранее реализованные Pipeline и не изменяет внутреннюю структуру специализированных Adapter. Он исключительно расширяет существующий механизм Unified Routing новым типом сообщений. # Реализованный уровень Unified Routing В файл ```text src/market_data/acquisition/adapters/dzengi/websocket.py ``` добавлен специализированный Adapter ```text DzengiWebSocketTradeAdapter ``` Новый Adapter становится частью существующей архитектуры маршрутизации WebSocket-сообщений и отвечает исключительно за подключение уже реализованного транспортного Pipeline Trade к Unified Router. Во время обработки сообщения Adapter последовательно выполняет: 1. Schema Validation; 2. WebSocket Trade Adapter. При этом полный транспортный Pipeline продолжает оставаться инкапсулированным внутри ранее реализованного Adapter Build 060.14. После успешного завершения обработки вызывающая сторона получает готовую каноническую модель ```text Trade ``` Промежуточные транспортные модели по-прежнему не покидают слой адаптеров. --- # Почему маршрутизация выполняется в Unified Adapter Во время проектирования отдельно рассматривался вопрос о переносе логики определения типа сообщения в Runtime. По результатам анализа данный вариант был отклонён. Основные причины: - Runtime не должен знать типы рыночных сообщений; - Runtime не должен зависеть от конкретной биржи; - Runtime не должен содержать транспортную маршрутизацию; - вся логика определения типа сообщения уже сосредоточена в Unified Adapter. Таким образом архитектурная ответственность остаётся неизменной. Runtime отвечает исключительно за получение транспортных сообщений. Unified Adapter отвечает исключительно за определение их типа. Специализированные Adapter отвечают исключительно за преобразование данных. Подобное разделение полностью соответствует базовым архитектурным принципам Dzentra. --- # Последовательность обработки После завершения Build полный конвейер обработки WebSocket-сообщений принимает следующий вид. ```text Raw WebSocket Message │ ▼ DzengiUnifiedWebSocketAdapter │ ├────────► Quote Adapter │ │ │ ▼ │ Quote │ ├────────► OHLC Adapter │ │ │ ▼ │ CandleCloseEvent │ └────────► Trade Adapter │ ▼ Schema Validation │ ▼ WebSocket Trade Adapter │ ├────────► Parser ├────────► Value Validation ├────────► Mapper │ ▼ Trade ``` Каждый уровень Pipeline сохраняет собственную область ответственности. Ни один из существующих компонентов не изменяет своё назначение. --- # Использование существующих компонентов Build 060.15 не вводит новых механизмов обработки транспортных данных. Unified Router повторно использует уже существующую инфраструктуру проекта. Для обработки Quote используются: ```text DzengiWebSocketQuoteAdapter ``` Для обработки OHLC используются: ```text DzengiWebSocketOhlcAdapter ``` Для обработки Trade используются: ```text DzengiWebSocketTradeAdapter ``` Новый специализированный Adapter, в свою очередь, повторно использует ранее реализованный ```text adapt_websocket_trade_document(...) ``` из Build 060.14. Таким образом Build не дублирует существующую функциональность и полностью основан на уже реализованных компонентах проекта. --- # Проброс исключений Unified Router не выполняет собственной обработки ошибок. Все исключения специализированных Adapter пробрасываются вызывающей стороне без изменения. При обработке Quote сохраняется существующий механизм обработки ошибок. При обработке OHLC сохраняется существующий механизм обработки ошибок. При обработке Trade сохраняются исключения: ```text TradeSchemaError ``` ```text TradeParseError ``` ```text TradeValueError ``` ```text TradeMappingError ``` Подобный подход сохраняет единообразную архитектуру обработки ошибок во всей подсистеме Market Data Acquisition. --- # Изменённые файлы В рамках Build были изменены только два файла. ## Unified Adapter ```text src/market_data/acquisition/adapters/dzengi/websocket.py ``` Добавлен специализированный ```text DzengiWebSocketTradeAdapter ``` и расширена маршрутизация сообщений. Существующая логика обработки Quote и OHLC не изменялась. --- ## Unit-тесты ```text tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_unified_adapter.py ``` Добавлен unit-тест маршрутизации сообщений ```text internal.trade ``` Все существующие тесты сохранены без изменений. --- # Добавленные тесты В рамках Build реализован дополнительный unit-тест, подтверждающий корректную маршрутизацию сообщений ```text internal.trade ``` через Unified Router. --- ## Проверка успешной маршрутизации Trade Подтверждается, что сообщение ```text destination = "internal.trade" ``` автоматически направляется в специализированный ```text DzengiWebSocketTradeAdapter ``` и после завершения полного транспортного Pipeline возвращается каноническая модель ```text Trade ``` --- # Результаты тестирования После завершения реализации выполнен запуск целевого набора unit-тестов нового Adapter. ```bash PYTHONPATH="$PWD" python -m pytest \ tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_trade_adapter.py -v ``` Результат: ```text 4 passed ``` --- После этого выполнено тестирование Unified Router. ```bash PYTHONPATH="$PWD" python -m pytest \ tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_unified_adapter.py -v ``` Результат: ```text 10 passed ``` Подтверждена корректная маршрутизация: - Quote; - OHLC; - Trade. Также подтверждено отсутствие изменений существующей функциональности. --- # Регрессионное тестирование Adapter После завершения реализации выполнен полный запуск тестов адаптеров Dzengi. ```bash PYTHONPATH="$PWD" python -m pytest \ tests/unit/market_data/acquisition/adapters/dzengi ``` Результат: ```text 302 passed ``` Регрессий существующих Adapter, Parser, Mapper и Validation не обнаружено. --- # Регрессионное тестирование Market Data После завершения реализации выполнен запуск полного набора unit-тестов подсистемы Market Data. ```bash PYTHONPATH="$PWD" python -m pytest \ tests/unit/market_data ``` Результат: ```text 914 passed ``` Подтверждено отсутствие регрессий во всех ранее реализованных компонентах подсистемы. --- # Полное регрессионное тестирование После завершения реализации выполнен полный запуск unit-тестов проекта. ```bash PYTHONPATH="$PWD" python -m pytest ``` Результат: ```text 1235 passed ``` Регрессий существующей функциональности не обнаружено. Добавление поддержки Trade в Unified Routing не повлияло на существующие механизмы обработки Quote, OHLC, REST Trade и остальные подсистемы проекта. # Проверка компиляции После завершения реализации выполнена полная проверка компиляции проекта. ```bash python -m compileall src tests ``` Компиляция завершилась успешно. Ошибок синтаксиса не обнаружено. Все изменённые файлы успешно компилируются и не нарушают целостность проекта. --- # Проверка Git diff После завершения реализации выполнена финальная проверка изменений. ```bash git diff --check ``` Результат: ```text без замечаний ``` Проверка подтвердила отсутствие: - trailing whitespace; - ошибок окончания строк; - конфликтов diff; - нарушений форматирования. --- # Scope Build 060.15 В рамках данного Build реализован исключительно уровень ```text Unified WebSocket Routing ``` Build **не включает**: - WebSocket Runtime; - WebSocket Protocol; - Trades Feed; - Dispatcher; - Event Bus; - Runtime Integration; - обработку торговых решений. Подобное ограничение полностью соответствует принятому принципу атомарной реализации Build. Каждый этап дорожной карты реализует только один архитектурный уровень системы. --- # Архитектурный результат После завершения Build система содержит полностью реализованный механизм Unified WebSocket Routing. Конвейер обработки принимает следующий вид. ```text Raw WebSocket Message │ ▼ DzengiUnifiedWebSocketAdapter │ ├────────► Quote Adapter │ │ │ ▼ │ Quote │ ├────────► OHLC Adapter │ │ │ ▼ │ CandleCloseEvent │ └────────► Trade Adapter │ ▼ Trade ``` Unified Router полностью изолирует вызывающий код от деталей транспортного Pipeline. Все специализированные Adapter продолжают самостоятельно выполнять полный цикл преобразования транспортных данных в канонические модели предметной области. --- # Состояние WebSocket Trade Pipeline После завершения Build 060.15 транспортный конвейер принимает следующий вид. ```text Raw WebSocket Trade │ ▼ Unified WebSocket Routing │ ▼ Schema Validation │ ▼ ValidatedWebSocketTradeDocument │ ▼ Adapter │ ├────────► Parser │ ├────────► Value Validation │ ├────────► Mapper │ ▼ Trade ``` Статус реализации компонентов: | Компонент | Build | Статус | |-----------|-------|--------| | Canonical Trade Model | 060.1 | ✔ Completed | | WebSocket Trade Transport Model | 060.9 | ✔ Completed | | WebSocket Trade Schema Validation | 060.10 | ✔ Completed | | WebSocket Trade Parser | 060.11 | ✔ Completed | | WebSocket Trade Value Validation | 060.12 | ✔ Completed | | WebSocket Trade Mapper | 060.13 | ✔ Completed | | WebSocket Trade Adapter | 060.14 | ✔ Completed | | Unified WebSocket Routing | 060.15 | ✔ Completed | | Trades Feed | 060.16 | Pending | --- # Соблюдение архитектурных принципов В рамках Build полностью сохранены архитектурные инварианты Dzentra. ## Локальность изменений Изменены только: - `src/market_data/acquisition/adapters/dzengi/websocket.py`; - `tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_unified_adapter.py`. Все остальные компоненты проекта остались без изменений. --- ## Повторное использование архитектуры Build полностью использует существующую архитектуру Unified Router. Новый механизм маршрутизации не проектировался. Расширен уже существующий механизм обработки сообщений. --- ## Повторное использование инфраструктуры Build полностью использует ранее реализованные компоненты проекта: - Quote Adapter; - OHLC Adapter; - WebSocket Trade Adapter. Новые Parser, Mapper или Validation не создавались. Вся существующая инфраструктура используется повторно. --- ## Разделение ответственности Unified Router отвечает исключительно за определение типа входящего сообщения. Специализированные Adapter отвечают исключительно за преобразование транспортных данных. Runtime продолжает отвечать исключительно за получение транспортных сообщений. Подобное разделение полностью соответствует архитектурным принципам Dzentra. --- ## Обратная совместимость Существующая обработка: - Quote; - OHLC; - REST Trade; не изменилась. Добавленная поддержка Trade полностью совместима с существующей архитектурой и не оказывает влияния на ранее реализованные компоненты проекта. --- # Архитектурные решения Build (ADR) ## ADR-060.15-001 **Определение типа WebSocket-сообщения выполняется исключительно Unified Router.** Runtime не должен содержать транспортную маршрутизацию. --- ## ADR-060.15-002 **Каждый тип рыночных данных обрабатывается собственным специализированным Adapter.** Unified Router не выполняет преобразование транспортных данных. Он только определяет тип сообщения и передаёт его соответствующему Adapter. --- ## ADR-060.15-003 **Trade Pipeline повторно использует ранее реализованный Adapter Build 060.14.** Unified Router не вызывает Parser, Value Validation и Mapper напрямую. Полный транспортный Pipeline остаётся полностью инкапсулированным внутри специализированного Adapter. --- ## ADR-060.15-004 **Подключение нового типа сообщений не изменяет существующую архитектуру Runtime.** Поддержка Trade реализуется исключительно расширением Unified Router. Это сохраняет независимость Runtime от особенностей конкретных транспортных сообщений. --- # Критерии завершения Build Build 060.15 считается завершённым, поскольку выполнены все поставленные задачи. - ✔ реализован `DzengiWebSocketTradeAdapter`; - ✔ Trade подключён к Unified Router; - ✔ добавлена маршрутизация сообщений `internal.trade`; - ✔ Runtime не изменён; - ✔ транспортный Pipeline Trade повторно использован без дублирования; - ✔ сохранено разделение ответственности между Runtime, Router и Adapter; - ✔ добавлен unit-тест маршрутизации Trade; - ✔ успешно пройдены целевые тесты; - ✔ успешно пройдена регрессия Adapter; - ✔ успешно пройдена регрессия Market Data; - ✔ успешно пройдена полная регрессия проекта (`1235 passed`); - ✔ проект успешно компилируется; - ✔ `git diff --check` не выявил замечаний; - ✔ изменения полностью укладываются в согласованный scope Build. --- # Следующий этап Следующим этапом дорожной карты является ```text Build 060.16 — Trades Feed ``` Цель следующего Build: - реализовать специализированный Feed обработки сделок; - подключить поток Trade к инфраструктуре Market Data Acquisition; - обеспечить публикацию канонических моделей `Trade`; - подготовить основу для дальнейшего использования сделок подсистемами анализа рынка и торговых стратегий. --- # Итог Build 060.15 завершил интеграцию **WebSocket Trade Pipeline** в существующий механизм Unified WebSocket Routing. Новая реализация полностью повторно использует архитектуру Dzentra, не изменяет Runtime, не дублирует транспортный Pipeline и сохраняет строгое разделение ответственности между компонентами системы. После завершения Build все три типа рыночных данных — **Quote**, **CandleCloseEvent** и **Trade** — обрабатываются единым механизмом маршрутизации и возвращаются в виде канонических моделей предметной области. Build ограничен согласованным scope, успешно прошёл целевое и полное регрессионное тестирование, подтвердил отсутствие регрессий и завершил интеграцию WebSocket Trade в общий механизм маршрутизации Market Data Acquisition.