32 KiB
Build 060.10 — WebSocket Trade Schema Validation
Engineering Migration Report
Контроль документа
| Свойство | Значение |
|---|---|
| Build | 060.10 |
| Название | WebSocket Trade Schema Validation |
| Статус | Completed |
| Проект | Dzentra |
| Подсистема | Market Data Acquisition |
| Компонент | Trades Feed |
| Версия | 1.0 |
Цель Build
После завершения Build 060.9 система получила транспортную модель WebSocket Trade (DzengiWebSocketTradeEvent), описывающую одно событие биржи на транспортном уровне.
Следующим обязательным этапом развития WebSocket-конвейера является реализация слоя структурной проверки входящих сообщений.
Build 060.10 вводит механизм Schema Validation для сообщений Dzengi WebSocket канала internal.trade.
Основная задача Build — гарантировать, что последующие этапы обработки получают структурно корректный документ, содержащий все обязательные элементы транспортного контракта.
Данный Build ограничивается исключительно проверкой структуры сообщения и не затрагивает:
- Parser;
- Value Validation;
- Mapper;
- Adapter;
- Runtime;
- Routing;
- Trades Feed.
Предпосылки
К моменту начала Build архитектура Dzentra уже содержала завершённые уровни Schema Validation для остальных типов WebSocket-событий.
WebSocket Quote
Raw WebSocket Quote
│
▼
Schema Validation
│
▼
ValidatedWebSocketQuoteDocument
│
▼
Quote Parser
WebSocket OHLC
Raw WebSocket OHLC
│
▼
Schema Validation
│
▼
ValidatedWebSocketOhlcDocument
│
▼
OHLC Parser
После завершения Build 060.9 появилась транспортная модель:
DzengiWebSocketTradeEvent
Однако между необработанным JSON-документом и Parser отсутствовал слой, отвечающий за структурную проверку сообщения.
В результате WebSocket-конвейер обработки сделок оставался незавершённым и отличался от уже реализованных конвейеров Quote и OHLC.
Архитектурное основание
В архитектуре Dzentra каждый уровень Pipeline имеет строго определённую область ответственности.
Schema Validation располагается между транспортным JSON-документом и Parser и отвечает исключительно за проверку структуры сообщения.
На данном уровне выполняется:
- проверка структуры корневого объекта;
- проверка обязательных элементов транспортной оболочки;
- проверка структуры объекта
payload; - проверка наличия обязательных полей транспортного события.
Schema Validation принципиально не выполняет:
- преобразование типов;
- преобразование числовых значений;
- проверку диапазонов;
- проверку бизнес-семантики;
- создание транспортной модели;
- преобразование в каноническую модель
Trade.
Такое разделение позволяет каждому уровню Pipeline выполнять одну строго определённую задачу и исключает смешивание ответственности между компонентами.
Результаты архитектурного аудита
Перед началом реализации был выполнен аудит существующей подсистемы Validation.
Подтверждено наличие полностью реализованных компонентов:
ValidatedWebSocketQuoteDocument;ValidatedWebSocketOhlcDocument;validate_dzengi_websocket_quote_schema();validate_dzengi_websocket_ohlc_schema().
Также подтверждено существование полной иерархии ошибок обработки Trade:
TradeTransportError;TradeSchemaError;TradeParseError;TradeValueError;TradeMappingError.
Одновременно подтверждено отсутствие собственного уровня Schema Validation для WebSocket Trade.
Таким образом Build 060.10 полностью соответствует утверждённой дорожной карте серии 060 и закрывает второй этап WebSocket-ветки обработки сделок.
Архитектурное решение
По итогам аудита было принято решение не проектировать отдельную архитектуру для Trade.
Вместо этого реализован третий экземпляр уже существующего архитектурного шаблона.
В систему добавлены:
ValidatedWebSocketTradeDocument
validate_dzengi_websocket_trade_schema(...)
Архитектура всех WebSocket-конвейеров стала полностью симметричной.
Quote
Raw WebSocket
│
▼
Schema Validation
│
▼
ValidatedWebSocketQuoteDocument
OHLC
Raw WebSocket
│
▼
Schema Validation
│
▼
ValidatedWebSocketOhlcDocument
Trade
Raw WebSocket
│
▼
Schema Validation
│
▼
ValidatedWebSocketTradeDocument
Build 060.10 не изменяет существующее поведение Quote и OHLC, а лишь расширяет существующую архитектуру новым типом рыночных данных.
Реализованный документ Schema Validation
В файл
src/market_data/acquisition/validation/schema.py
добавлен новый документ структурной проверки:
@dataclass(frozen=True, slots=True)
class ValidatedWebSocketTradeDocument:
payload: Mapping[str, object]
status: object
destination: object
correlation_id: object | None
Документ представляет собой неизменяемый результат успешной проверки структуры WebSocket-сообщения.
Экземпляр содержит:
- транспортную оболочку сообщения;
- неизменяемый
payload; - статус сообщения;
- назначение сообщения;
- необязательный
correlationId.
После создания объект используется исключительно последующими стадиями Pipeline и не предполагает модификации.
Почему используется отдельный документ Validation
ValidatedWebSocketTradeDocument не является транспортной моделью биржи.
Он представляет собой результат успешной структурной проверки входящего JSON-документа.
Документ:
- не содержит бизнес-логики;
- не преобразует данные;
- не выполняет Parsing;
- не выполняет Value Validation;
- не выполняет Mapping;
- не является канонической моделью
Trade.
Его единственная задача — гарантировать Parser, что структура сообщения соответствует ожидаемому контракту.
Такое разделение полностью повторяет архитектурный подход, уже применяемый для Quote и OHLC.
Проверяемая структура WebSocket-документа
В рамках Build 060.10 реализована проверка исключительно структуры сообщения.
Ожидаемый контракт WebSocket-события имеет следующий вид:
{
"status": "OK",
"destination": "internal.trade",
"payload": {
"buyer": false,
"id": 2134846831,
"orderId": "00a02503-0079-54c4-0000-000081e62b58",
"price": 64555.55,
"size": 0.002,
"symbol": "BTC/USD_LEVERAGE",
"ts": 1784218012030
}
}
Build 060.10 гарантирует наличие обязательных элементов данного контракта, но принципиально не анализирует их содержимое.
Проверяемые элементы транспортной оболочки
На уровне корневого документа выполняется проверка наличия обязательных полей:
status
destination
payload
Кроме того, проверяется, что сам корневой объект является JSON Mapping и содержит только строковые ключи.
Поле
correlationId
не является обязательным.
При наличии оно сохраняется в результирующем документе без какой-либо дополнительной обработки.
Следует отметить, что Build 060.10 проверяет наличие поля
destination
но не проверяет его значение.
В частности, валидатор не сравнивает содержимое поля со строкой
internal.trade
Подобная проверка относится не к структурной корректности сообщения, а к его семантике и поэтому не входит в область ответственности Schema Validation.
Такое разделение полностью соответствует архитектурному принципу Dzentra, согласно которому Schema Validation отвечает исключительно за структуру входящего документа, а не за интерпретацию его содержимого.
Проверяемые элементы payload
После успешной проверки транспортной оболочки выполняется проверка структуры объекта
payload
Payload обязан быть JSON Mapping.
Для объекта выполняется проверка строковых ключей и наличие обязательных элементов транспортного контракта.
Обязательными являются:
id
price
size
symbol
ts
buyer
orderId
Отсутствие любого из перечисленных полей приводит к генерации исключения
TradeSchemaError
с указанием отсутствующих элементов.
Проверка Mapping
Build 060.10 следует архитектурному правилу Dzentra:
любая структура JSON после прохождения Schema Validation должна представлять собой Mapping со строковыми ключами.
Поэтому реализованы две независимые проверки.
Первая проверяет корневой документ:
$
Вторая проверяет вложенный объект:
$.payload
В обоих случаях:
- объект обязан быть Mapping;
- каждый ключ обязан иметь тип
str.
Подобный подход полностью совпадает с реализацией Quote и OHLC.
Использование MappingProxyType
После успешной проверки содержимое
payload
копируется в
MappingProxyType(dict(payload))
Таким образом создаётся неизменяемое представление транспортного документа.
Использование MappingProxyType решает сразу несколько задач.
Во-первых, предотвращается случайное изменение данных после завершения Schema Validation.
Во-вторых, исключается влияние внешнего кода на результаты проверки структуры.
В-третьих, последующие уровни Pipeline получают гарантированно неизменяемый документ.
Parser, Value Validation и Mapper могут безопасно использовать полученные данные, не опасаясь их изменения между этапами обработки.
Почему не используется транспортная модель
Build 060.10 принципиально не создаёт экземпляр
DzengiWebSocketTradeEvent
Это является обязанностью Parser.
Schema Validation лишь подтверждает корректность структуры сообщения.
Создание транспортной модели переносится на следующий Build.
Подобное разделение ответственности уже используется в существующих WebSocket-конвейерах Quote и OHLC.
Граница ответственности Build
Build 060.10 отвечает исключительно за структурную корректность документа.
В его обязанности входит:
- проверка структуры корневого объекта;
- проверка транспортной оболочки;
- проверка структуры payload;
- проверка обязательных полей;
- формирование неизменяемого документа Validation.
Build не выполняет:
- Parsing;
- преобразование JSON в транспортную модель;
- преобразование типов;
- Decimal-конвертацию;
- проверку диапазонов;
- проверку timestamp;
- проверку символа;
- проверку стороны сделки;
- Mapping;
- создание канонической модели
Trade.
Каждая из перечисленных задач относится к отдельному архитектурному уровню и будет реализована в следующих Build.
Использование TradeSchemaError
Для всех ошибок структуры используется уже существующее исключение
TradeSchemaError
Build не вводит новых типов исключений.
Это сохраняет единый подход ко всей подсистеме Validation и полностью соответствует существующей архитектуре обработки ошибок.
Целевой конвейер обработки WebSocket Trade
После завершения Build 060.10 конвейер обработки принимает следующий вид.
Raw WebSocket Object
│
▼
WebSocket Trade Schema Validation
│
▼
ValidatedWebSocketTradeDocument
│
▼
Build 060.11 — WebSocket Trade Parser
│
▼
DzengiWebSocketTradeEvent
│
▼
Build 060.12 — WebSocket Trade Value Validation
│
▼
Validated Trade Transport Event
│
▼
Build 060.13 — WebSocket Trade Mapper
│
▼
Trade
Таким образом Build 060.10 завершает второй архитектурный уровень WebSocket-конвейера обработки сделок.
Соотношение с транспортной моделью
Build 060.9 и Build 060.10 реализуют два различных архитектурных уровня.
Build 060.9
вводит транспортную модель
DzengiWebSocketTradeEvent
которая описывает уже разобранное WebSocket-событие.
Build 060.10
вводит документ
ValidatedWebSocketTradeDocument
который представляет собой результат проверки структуры исходного JSON-документа.
Таким образом последовательность обработки становится следующей.
Raw JSON
│
▼
ValidatedWebSocketTradeDocument
│
▼
DzengiWebSocketTradeEvent
│
▼
Trade
Каждый объект относится к собственному архитектурному уровню и не дублирует ответственность другого.
Изменённые файлы
В рамках Build были изменены только два файла.
Schema Validation
src/market_data/acquisition/validation/schema.py
Добавлены:
ValidatedWebSocketTradeDocument
validate_dzengi_websocket_trade_schema(...)
_validate_websocket_trade_payload(...)
_require_websocket_trade_mapping(...)
При этом существующие валидаторы Quote и OHLC, импорты и поведение файла не изменялись.
Unit-тесты
tests/unit/market_data/acquisition/validation/test_websocket_trade_schema.py
Добавлен полный набор unit-тестов нового уровня Schema Validation.
Добавленные тесты
В рамках Build реализовано двадцать unit-тестов, полностью покрывающих функциональность нового валидатора.
Проверка успешной валидации
Тест
test_validate_websocket_trade_schema_returns_immutable_document
проверяет:
- успешную проверку корректного документа;
- создание
ValidatedWebSocketTradeDocument; - использование
MappingProxyType; - сохранение обязательных полей.
Проверка correlationId
Тест
test_validate_websocket_trade_schema_preserves_correlation_id
подтверждает корректное сохранение необязательного поля
correlationId.
Проверка копирования payload
Тест
test_validate_websocket_trade_schema_copies_payload
подтверждает, что изменения исходного словаря после Validation не влияют на содержимое результирующего документа.
Проверка структуры корневого объекта
Тест
test_validate_websocket_trade_schema_rejects_non_mapping_root
подтверждает генерацию TradeSchemaError,
если корневой объект не является JSON Mapping.
Проверка обязательных полей транспортной оболочки
Параметризованный тест
test_validate_websocket_trade_schema_rejects_missing_root_field
проверяет отсутствие:
- status;
- destination;
- payload.
Проверка структуры payload
Тест
test_validate_websocket_trade_schema_rejects_non_mapping_payload
проверяет, что поле payload
обязано быть JSON Mapping.
Проверка обязательных полей Trade
Параметризованный тест
test_validate_websocket_trade_schema_rejects_missing_payload_field
проверяет отсутствие каждого обязательного элемента:
- id;
- price;
- size;
- ts;
- symbol;
- buyer;
- orderId.
Проверка сообщения об ошибке
Тест
test_validate_websocket_trade_schema_reports_all_missing_fields
подтверждает, что исключение содержит полный список отсутствующих полей.
Отсутствие проверки значений
Тест
test_validate_websocket_trade_schema_does_not_validate_values
подтверждает архитектурный принцип Build.
Schema Validation проверяет исключительно структуру и принципиально не анализирует содержимое полей.
Дополнительные поля
Тест
test_validate_websocket_trade_schema_allows_additional_fields
подтверждает, что неподтверждённые Production поля не вызывают ошибку Validation.
В частности проверяется возможность присутствия
clientOrderId
и других дополнительных элементов.
Проверка строковых ключей
Реализованы отдельные тесты проверки строковых ключей для:
- корневого объекта;
- объекта payload.
Это полностью соответствует архитектуре существующих WebSocket Schema Validation.
Результаты тестирования
Выполнен целевой запуск нового набора unit-тестов.
python -m pytest \
tests/unit/market_data/acquisition/validation/test_websocket_trade_schema.py \
-q
Результат:
20 passed in 0.02s
Все проверки новой функциональности успешно завершены.
Регрессионное тестирование
После завершения реализации выполнен полный запуск подсистемы Validation.
python -m pytest \
tests/unit/market_data/acquisition/validation \
-q
Результат:
302 passed in 0.10s
Регрессий существующей функциональности не обнаружено.
Проверка компиляции
Выполнена проверка компиляции изменённых файлов.
python -m compileall \
src/market_data/acquisition/validation/schema.py \
tests/unit/market_data/acquisition/validation/test_websocket_trade_schema.py
Компиляция завершилась успешно.
Синтаксические ошибки отсутствуют.
Проверка Git diff
Выполнена финальная проверка изменений.
git diff --check
Ошибок не обнаружено.
Это подтверждает отсутствие:
- trailing whitespace;
- конфликтов окончания строк;
- ошибок форматирования diff.
Scope Build 060.10
В рамках данного Build реализовано только:
WebSocket Trade Schema Validation
Build не включает:
- WebSocket Trade Parser;
- WebSocket Trade Value Validation;
- WebSocket Trade Mapper;
- WebSocket Trade Adapter;
- Runtime Integration;
- Unified Routing;
- Trades Feed.
Это полностью соответствует принципу атомарной реализации Build.
Архитектурный результат
После завершения Build система содержит завершённый уровень Schema Validation для всех поддерживаемых WebSocket-событий.
Quote
Raw WebSocket
│
▼
Schema Validation
│
▼
ValidatedWebSocketQuoteDocument
OHLC
Raw WebSocket
│
▼
Schema Validation
│
▼
ValidatedWebSocketOhlcDocument
Trade
Raw WebSocket
│
▼
Schema Validation
│
▼
ValidatedWebSocketTradeDocument
Архитектура стала полностью симметричной.
Состояние WebSocket Trade Pipeline
После завершения Build 060.10 конвейер имеет следующий вид.
Raw WebSocket Trade Document
│
▼
ValidatedWebSocketTradeDocument
│
▼
Parser
│
▼
DzengiWebSocketTradeEvent
│
▼
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 | Pending |
| WebSocket Trade Value Validation | 060.12 | Pending |
| WebSocket Trade Mapper | 060.13 | Pending |
| WebSocket Trade Adapter | 060.14 | Pending |
| Unified WebSocket Routing | 060.15 | Pending |
Соблюдение архитектурных принципов
В рамках Build полностью сохранены архитектурные инварианты Dzentra.
Локальность изменений
Изменены только:
- Schema Validation;
- unit-тесты нового валидатора.
Повторное использование архитектуры
Новая реализация полностью повторяет существующий шаблон Quote и OHLC.
Новая архитектура не создавалась.
Разделение ответственности
Schema Validation отвечает исключительно за проверку структуры сообщения.
Parser, Value Validation, Mapper и Runtime остаются полностью независимыми уровнями.
Отсутствие бизнес-логики
Build не выполняет:
- Parsing;
- преобразование типов;
- Value Validation;
- Mapping;
- Runtime Integration.
Это полностью соответствует архитектуре Dzentra.
Обратная совместимость
Существующая обработка Quote, OHLC и REST Trade не изменилась.
Новая функциональность добавлена изолированно и не влияет на ранее реализованные Build.
Критерии завершения Build
Build 060.10 считается завершённым, поскольку выполнены все поставленные задачи.
- ✔ реализован
ValidatedWebSocketTradeDocument; - ✔ реализована функция
validate_dzengi_websocket_trade_schema(); - ✔ проверяется структура транспортной оболочки;
- ✔ проверяется структура payload;
- ✔ проверяются обязательные поля Trade;
- ✔ используется
TradeSchemaError; - ✔ payload становится неизменяемым;
- ✔ реализовано двадцать unit-тестов;
- ✔ все целевые тесты успешно проходят;
- ✔ регрессионное тестирование успешно завершено;
- ✔ компиляция выполнена без ошибок;
- ✔
git diff --checkне выявил замечаний; - ✔ изменения не выходят за пределы согласованного scope.
Следующий этап
Следующим этапом дорожной карты является
Build 060.11 — WebSocket Trade Parser
Цель Build:
- преобразование
ValidatedWebSocketTradeDocument; - создание транспортной модели
DzengiWebSocketTradeEvent; - нормализация имён транспортных полей;
- преобразование JSON-ключей:
id → trade_id;ts → timestamp;orderId → order_id;
- сохранение исходных числовых значений без преобразования типов;
- отсутствие Value Validation.
После завершения Build 060.11 конвейер примет следующий вид:
Raw WebSocket Object
│
▼
Schema Validation
│
▼
ValidatedWebSocketTradeDocument
│
▼
WebSocket Trade Parser
│
▼
DzengiWebSocketTradeEvent
Build 060.11 по-прежнему не будет выполнять:
- проверку диапазонов значений;
- проверку корректности timestamp;
- проверку корректности цены и объёма;
- Mapping в каноническую модель
Trade; - Runtime Integration.
Все перечисленные задачи будут реализованы на последующих этапах дорожной карты серии 060.
Итог
Build 060.10 завершил формирование уровня Schema Validation для WebSocket Trade и сделал архитектуру обработки всех WebSocket-событий Dzentra полностью симметричной.
Новая реализация основана на существующем шаблоне Quote и OHLC, использует единый подход к структурной проверке сообщений, повторно применяет существующую иерархию исключений и не изменяет ранее реализованное поведение системы.
Build ограничен согласованным scope, успешно прошёл целевое и регрессионное тестирование и создаёт необходимый фундамент для следующего этапа — Build 060.11 — WebSocket Trade Parser.