31 KiB
Build 060.14 — WebSocket Trade Adapter
Engineering Migration Report
Контроль документа
| Свойство | Значение |
|---|---|
| Build | 060.14 |
| Название | WebSocket Trade Adapter |
| Статус | Completed |
| Проект | Dzentra |
| Подсистема | Market Data Acquisition |
| Компонент | Trades Feed |
| Версия | 1.0 |
Цель Build
После завершения Build 060.13 система получила полностью реализованный уровень WebSocket Trade Mapper, выполняющий преобразование транспортной модели
DzengiWebSocketTradeEvent
в каноническую модель предметной области
Trade
На данном этапе Pipeline уже гарантирует:
- корректность структуры транспортного документа;
- успешное построение транспортной модели;
- корректность всех обязательных значений;
- успешное преобразование транспортной модели в каноническую модель предметной области.
Однако все реализованные уровни Pipeline по-прежнему существовали как независимые компоненты.
Для получения канонической модели сделки вызывающей стороне необходимо было самостоятельно выполнить последовательность операций:
Parser
│
▼
Value Validation
│
▼
Mapper
Подобный подход противоречит одному из базовых архитектурных принципов Dzentra.
Внутренние компоненты системы не должны знать устройство транспортного Pipeline и порядок вызова его отдельных этапов.
Для решения данной задачи архитектура Dzentra предусматривает следующий обязательный уровень —
Adapter.
Именно Adapter объединяет все ранее реализованные уровни обработки в единую точку входа.
Build 060.14 реализует данный уровень для WebSocket Trade.
Основная задача Build — предоставить единственную функцию, принимающую уже прошедший Schema Validation документ
ValidatedWebSocketTradeDocument
и возвращающую готовую каноническую модель
Trade
выполняя внутри себя весь необходимый конвейер обработки.
При этом Build не затрагивает:
- Schema Validation;
- Parser;
- Value Validation;
- Mapper;
- WebSocket Runtime;
- Routing;
- Trades Feed.
Предпосылки
К началу Build архитектура Market Data Acquisition уже содержала полностью реализованный Adapter для REST Aggregate Trade.
Он объединял несколько архитектурных уровней в единую функцию обработки.
Конвейер REST Trade имел следующий вид.
ValidatedRestAggTradesDocument
│
▼
Parser
│
▼
Value Validation
│
▼
Mapper
│
▼
tuple[Trade]
Для WebSocket Trade после завершения Build 060.13 существовали все необходимые уровни Pipeline.
ValidatedWebSocketTradeDocument
│
▼
Parser
│
▼
DzengiWebSocketTradeEvent
│
▼
Value Validation
│
▼
DzengiWebSocketTradeEvent
│
▼
Mapper
│
▼
Trade
Однако единая точка входа отсутствовала.
Каждый уровень необходимо было вызывать отдельно.
Таким образом архитектура WebSocket Trade оставалась незавершённой.
Архитектурное основание
Одним из фундаментальных принципов архитектуры Dzentra является инкапсуляция транспортного Pipeline внутри слоя адаптера.
Внутренние компоненты системы должны работать исключительно с готовыми каноническими моделями предметной области.
Полный Pipeline обработки рыночных данных имеет следующий вид.
Raw Source
│
▼
Schema Validation
│
▼
Validated Document
│
▼
Parser
│
▼
Transport Model
│
▼
Value Validation
│
▼
Transport Model
│
▼
Mapper
│
▼
Domain Model
Каждый уровень Pipeline отвечает исключительно за собственную область ответственности.
Однако вызывающий код не должен знать внутреннюю структуру данного конвейера.
Эта задача полностью возлагается на Adapter.
Для WebSocket Trade Adapter выполняет следующие действия.
Parser
создаёт транспортную модель
DzengiWebSocketTradeEvent
из прошедшего Schema Validation документа.
Value Validation
подтверждает корректность всех значений транспортной модели.
Mapper
преобразует транспортную модель в каноническую модель
Trade
После завершения Adapter вызывающая сторона получает уже готовую каноническую модель предметной области и не взаимодействует с транспортными моделями либо отдельными уровнями Pipeline.
Adapter принципиально не выполняет:
- Schema Validation;
- Runtime-логику;
- маршрутизацию сообщений;
- бизнес-логику;
- принятие торговых решений.
Подобное разделение ответственности делает транспортный Pipeline полностью инкапсулированным и повторно используемым.
Результаты архитектурного аудита
Перед реализацией Build был выполнен аудит существующей архитектуры Adapter.
В ходе анализа подтверждено наличие полностью реализованного Adapter для REST Aggregate Trade.
Его реализация использует единый архитектурный шаблон.
Validated Document
│
▼
Parser
│
▼
Value Validation
│
▼
Mapper
│
▼
Canonical Model
Также аудит подтвердил наличие всех необходимых компонентов WebSocket Trade:
- Schema Validation;
- Parser;
- Value Validation;
- Mapper.
Все перечисленные уровни были полностью реализованы предыдущими Build серии 060.
При этом собственный Adapter для WebSocket Trade отсутствовал.
Таким образом единственным отсутствующим элементом транспортного Pipeline являлась единая точка входа, объединяющая все ранее реализованные уровни.
Build 060.14 полностью устраняет данный пробел и завершает архитектурное построение адаптера обработки WebSocket Trade.
Архитектурное решение
По результатам проведённого аудита было принято решение полностью повторить архитектурный шаблон, уже используемый существующим REST Adapter.
В систему добавлена новая функция
adapt_websocket_trade_document(...)
которая принимает документ
ValidatedWebSocketTradeDocument
и внутри себя последовательно выполняет:
Parser
│
▼
Value Validation
│
▼
Mapper
После успешного завершения обработки вызывающая сторона получает единственный результат —
Trade
Конвейер WebSocket Trade принимает следующий вид.
ValidatedWebSocketTradeDocument
│
▼
WebSocket Trade Adapter
│
├────────► Parser
│
├────────► Value Validation
│
├────────► Mapper
│
▼
Trade
Build 060.14 не изменяет архитектуру ранее реализованных компонентов.
Все существующие уровни Pipeline продолжают существовать как самостоятельные независимые компоненты.
Adapter лишь объединяет их в единую точку входа, полностью соответствующую архитектурным принципам Dzentra.
Реализованный уровень Adapter
В файл
src/market_data/acquisition/adapters/dzengi/websocket_trade_adapter.py
добавлена новая функция
adapt_websocket_trade_document(...)
Функция принимает объект
ValidatedWebSocketTradeDocument
и полностью инкапсулирует транспортный Pipeline обработки WebSocket Trade.
Во время выполнения Adapter последовательно вызывает:
- Parser;
- Value Validation;
- Mapper.
После успешного завершения обработки вызывающая сторона получает готовую каноническую модель
Trade
При этом промежуточные транспортные модели не покидают слой адаптера.
Почему Adapter объединяет существующие уровни Pipeline
Во время архитектурного проектирования отдельно рассматривался вопрос о возможности прямого использования Parser, Value Validation и Mapper вызывающими компонентами системы.
По результатам анализа было принято решение отказаться от подобного подхода.
Основные причины:
- вызывающая сторона не должна знать внутреннюю структуру транспортного Pipeline;
- изменение последовательности этапов обработки не должно затрагивать внешний код;
- повторное использование Pipeline должно происходить через единую точку входа;
- транспортные модели должны оставаться внутренней деталью реализации слоя адаптера.
Поэтому Adapter становится единственным публичным способом получения канонической модели
Trade
из прошедшего Schema Validation документа.
Подобное решение полностью соответствует базовому архитектурному принципу Dzentra — полной инкапсуляции транспортного Pipeline.
Последовательность обработки
Adapter реализует строго фиксированную последовательность этапов.
ValidatedWebSocketTradeDocument
│
▼
Parser
│
▼
DzengiWebSocketTradeEvent
│
▼
Value Validation
│
▼
DzengiWebSocketTradeEvent
│
▼
Mapper
│
▼
Trade
Ни один из этапов не может быть пропущен.
Каждый последующий уровень получает результат предыдущего уровня без изменения общей архитектуры Pipeline.
Использование существующих компонентов
Build 060.14 не вводит новых механизмов обработки данных.
Adapter повторно использует уже существующие компоненты проекта.
Для построения транспортной модели используется:
parse_dzengi_websocket_trade(...)
Для проверки корректности значений используется:
validate_dzengi_websocket_trade_values(...)
Для построения канонической модели используется:
map_dzengi_websocket_trade_to_trade(...)
Таким образом Adapter полностью основан на ранее реализованной инфраструктуре и не дублирует существующую функциональность.
Проброс исключений
Adapter не выполняет собственную обработку ошибок.
Все исключения предыдущих уровней Pipeline пробрасываются вызывающей стороне без изменения.
При ошибке Parser генерируется
TradeParseError
При ошибке проверки значений генерируется
TradeValueError
При ошибке преобразования транспортной модели генерируется
TradeMappingError
Подобный подход сохраняет единообразную архитектуру обработки ошибок во всей подсистеме Market Data Acquisition.
Изменённые файлы
В рамках Build были изменены только два файла.
Adapter
src/market_data/acquisition/adapters/dzengi/websocket_trade_adapter.py
Добавлена функция
adapt_websocket_trade_document(...)
Ранее реализованные Parser, Value Validation и Mapper не изменялись.
Unit-тесты
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_trade_adapter.py
Добавлен полный набор unit-тестов нового Adapter.
Добавленные тесты
В рамках Build реализованы четыре unit-теста, полностью покрывающие функциональность Adapter.
Проверка успешной обработки
Подтверждается успешное получение канонической модели
Trade
из корректного объекта
ValidatedWebSocketTradeDocument
Одновременно подтверждается корректная работа полного Pipeline:
- Parser;
- Value Validation;
- Mapper.
Проверка ошибок Parser
Отдельный тест подтверждает корректный проброс исключения
TradeParseError
при ошибке построения транспортной модели.
Проверка ошибок Value Validation
Отдельный тест подтверждает корректный проброс исключения
TradeValueError
при обнаружении некорректных значений транспортной модели.
Проверка ошибок Mapper
Отдельный тест подтверждает корректный проброс исключения
TradeMappingError
при невозможности построения канонической модели.
Результаты тестирования
После завершения реализации выполнен запуск целевого набора unit-тестов.
PYTHONPATH=. pytest -q \
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_trade_adapter.py
Результат:
4 passed in 0.02s
Все проверки новой функциональности успешно завершены.
Новый набор тестов полностью покрывает:
- успешное выполнение полного Pipeline;
- корректное получение канонической модели
Trade; - проброс ошибок Parser;
- проброс ошибок Value Validation;
- проброс ошибок Mapper.
Регрессионное тестирование Adapter
После завершения реализации выполнен полный запуск тестов адаптеров Dzengi.
PYTHONPATH=. pytest -q \
tests/unit/market_data/acquisition/adapters/dzengi
Результат:
301 passed in 0.11s
Регрессий существующих Adapter, Parser, Mapper и Validation не обнаружено.
Регрессионное тестирование Market Data
После завершения реализации выполнен запуск полного набора unit-тестов подсистемы Market Data.
PYTHONPATH=. pytest -q \
tests/unit/market_data
Результат:
913 passed in 0.31s
Подтверждено отсутствие регрессий во всех ранее реализованных компонентах подсистемы.
Полное регрессионное тестирование
После завершения реализации выполнен полный запуск unit-тестов проекта.
PYTHONPATH=. pytest -q
Результат:
1234 passed in 2.10s
Регрессий существующей функциональности не обнаружено.
Все ранее реализованные Build продолжают работать без каких-либо изменений.
Это подтверждает, что добавленная функциональность полностью изолирована и не влияет на существующие конвейеры обработки Quote, OHLC, REST Trade и остальные подсистемы проекта.
Проверка компиляции
После завершения реализации выполнена полная проверка компиляции проекта.
python -m compileall src tests
Компиляция завершилась успешно.
Ошибок синтаксиса не обнаружено.
Все изменённые файлы успешно компилируются и не нарушают целостность проекта.
Проверка Git diff
После завершения реализации выполнена финальная проверка изменений.
git diff --check
Результат:
без замечаний
Проверка подтвердила отсутствие:
- trailing whitespace;
- ошибок окончания строк;
- конфликтов diff;
- нарушений форматирования.
Scope Build 060.14
В рамках данного Build реализован исключительно уровень
WebSocket Trade Adapter
Build не включает:
- WebSocket Runtime;
- Unified WebSocket Routing;
- Trades Feed;
- Dispatcher;
- Event Bus;
- Runtime Integration.
Подобное ограничение полностью соответствует принятому принципу атомарной реализации Build.
Каждый этап дорожной карты реализует только один архитектурный уровень Pipeline.
Архитектурный результат
После завершения Build система содержит полностью реализованный Adapter WebSocket Trade.
Конвейер обработки принимает следующий вид.
Raw WebSocket Trade
│
▼
Schema Validation
│
▼
ValidatedWebSocketTradeDocument
│
▼
WebSocket Trade Adapter
│
├────────► Parser
│
├────────► Value Validation
│
├────────► Mapper
│
▼
Trade
Таким образом Adapter полностью инкапсулирует транспортный Pipeline.
Внутренние компоненты системы получают уже готовую каноническую модель предметной области и не взаимодействуют с транспортными моделями либо отдельными этапами обработки.
Состояние WebSocket Trade Pipeline
После завершения Build 060.14 конвейер имеет следующий вид.
Raw WebSocket Trade
│
▼
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 | Pending |
Соблюдение архитектурных принципов
В рамках Build полностью сохранены архитектурные инварианты Dzentra.
Локальность изменений
Изменены только:
adapters/dzengi/websocket_trade_adapter.py;- unit-тесты нового Adapter.
Существующие Parser, Validation и Mapper не изменялись.
Повторное использование архитектуры
Новая реализация полностью повторяет архитектурный шаблон существующего REST Adapter.
Новая архитектура не проектировалась.
Использован уже существующий подход, применяемый для остальных источников рыночных данных.
Повторное использование инфраструктуры
Adapter полностью построен на ранее реализованных компонентах:
- Parser;
- Value Validation;
- Mapper.
Build не вводит новых механизмов обработки и не дублирует существующую функциональность.
Это обеспечивает единообразное поведение всех Adapter проекта.
Разделение ответственности
Adapter отвечает исключительно за объединение ранее реализованных уровней Pipeline.
Build не выполняет:
- Schema Validation;
- Runtime Integration;
- маршрутизацию событий;
- бизнес-логику;
- принятие торговых решений.
Все перечисленные задачи остаются ответственностью других архитектурных уровней.
Обратная совместимость
Существующая обработка:
- Quote;
- OHLC;
- REST Trade;
не изменилась.
Добавленная функциональность полностью изолирована и не оказывает влияния на ранее реализованные компоненты системы.
Архитектурные решения Build (ADR)
ADR-060.14-001
Adapter является единственной публичной точкой входа транспортного Pipeline.
Внутренние компоненты системы не должны самостоятельно вызывать Parser, Value Validation и Mapper.
ADR-060.14-002
Adapter не содержит собственной бизнес-логики.
Его задача ограничивается последовательным вызовом существующих уровней Pipeline.
ADR-060.14-003
Adapter не обрабатывает исключения предыдущих уровней.
Все ошибки Parser, Value Validation и Mapper пробрасываются вызывающей стороне без изменения.
Это сохраняет единый механизм обработки ошибок во всей подсистеме Market Data Acquisition.
ADR-060.14-004
Adapter повторно использует существующую инфраструктуру проекта.
Build не создаёт новых механизмов обработки данных.
Все этапы обработки выполняются уже существующими компонентами системы.
Критерии завершения Build
Build 060.14 считается завершённым, поскольку выполнены все поставленные задачи.
- ✔ реализована функция
adapt_websocket_trade_document(); - ✔ Adapter объединяет Parser, Value Validation и Mapper;
- ✔ реализована единая точка входа транспортного Pipeline;
- ✔ транспортный Pipeline полностью инкапсулирован;
- ✔ сохранено разделение ответственности между уровнями;
- ✔ исключения предыдущих уровней корректно пробрасываются;
- ✔ повторно использована существующая инфраструктура проекта;
- ✔ реализовано 4 unit-теста;
- ✔ целевой набор тестов успешно проходит;
- ✔ успешно пройдена регрессия Adapter;
- ✔ успешно пройдена регрессия Market Data;
- ✔ успешно пройдена полная регрессия проекта;
- ✔ проект успешно компилируется;
- ✔
git diff --checkне выявил замечаний; - ✔ изменения полностью укладываются в согласованный scope Build.
Следующий этап
Следующим этапом дорожной карты является
Build 060.15 — Unified WebSocket Routing
Цель следующего Build:
- подключить WebSocket Trade Adapter к существующему WebSocket Runtime;
- реализовать маршрутизацию сообщений по типам событий;
- передавать готовые объекты
Tradeв последующие уровни системы; - подготовить основу для реализации полноценного Trades Feed.
Итог
Build 060.14 завершил реализацию уровня WebSocket Trade Adapter и сделал транспортный Pipeline WebSocket Trade полностью инкапсулированным.
Новая реализация основана на уже существующих архитектурных принципах Dzentra, повторно использует Parser, Value Validation и Mapper, предоставляет единую точку входа для получения канонической модели Trade и сохраняет строгое разделение ответственности между архитектурными уровнями.
Build ограничен согласованным scope, успешно прошёл целевое и полное регрессионное тестирование, подтвердил отсутствие регрессий и завершил построение адаптера WebSocket Trade.
Следующим этапом развития серии является Build 060.15 — Unified WebSocket Routing, который интегрирует новый Adapter в общий WebSocket Runtime и завершит транспортный конвейер получения сделок в режиме реального времени.