Files
dzentra_bot/docs/migrations/build_060_10.md

1073 lines
32 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
```text
Raw WebSocket Quote
Schema Validation
ValidatedWebSocketQuoteDocument
Quote Parser
```
## WebSocket OHLC
```text
Raw WebSocket OHLC
Schema Validation
ValidatedWebSocketOhlcDocument
OHLC Parser
```
После завершения Build 060.9 появилась транспортная модель:
```text
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.
Вместо этого реализован третий экземпляр уже существующего архитектурного шаблона.
В систему добавлены:
```text
ValidatedWebSocketTradeDocument
validate_dzengi_websocket_trade_schema(...)
```
Архитектура всех WebSocket-конвейеров стала полностью симметричной.
```text
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
В файл
```text
src/market_data/acquisition/validation/schema.py
```
добавлен новый документ структурной проверки:
```python
@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-события имеет следующий вид:
```json
{
"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 гарантирует наличие обязательных элементов данного контракта, но принципиально не анализирует их содержимое.
---
# Проверяемые элементы транспортной оболочки
На уровне корневого документа выполняется проверка наличия обязательных полей:
```text
status
destination
payload
```
Кроме того, проверяется, что сам корневой объект является JSON Mapping и содержит только строковые ключи.
Поле
```text
correlationId
```
не является обязательным.
При наличии оно сохраняется в результирующем документе без какой-либо дополнительной обработки.
Следует отметить, что Build 060.10 проверяет **наличие** поля
```text
destination
```
но **не проверяет его значение**.
В частности, валидатор не сравнивает содержимое поля со строкой
```text
internal.trade
```
Подобная проверка относится не к структурной корректности сообщения, а к его семантике и поэтому не входит в область ответственности Schema Validation.
Такое разделение полностью соответствует архитектурному принципу Dzentra, согласно которому Schema Validation отвечает исключительно за структуру входящего документа, а не за интерпретацию его содержимого.
---
# Проверяемые элементы payload
После успешной проверки транспортной оболочки выполняется проверка структуры объекта
```text
payload
```
Payload обязан быть JSON Mapping.
Для объекта выполняется проверка строковых ключей и наличие обязательных элементов транспортного контракта.
Обязательными являются:
```text
id
price
size
symbol
ts
buyer
orderId
```
Отсутствие любого из перечисленных полей приводит к генерации исключения
```text
TradeSchemaError
```
с указанием отсутствующих элементов.
---
# Проверка Mapping
Build 060.10 следует архитектурному правилу Dzentra:
любая структура JSON после прохождения Schema Validation должна представлять собой Mapping со строковыми ключами.
Поэтому реализованы две независимые проверки.
Первая проверяет корневой документ:
```text
$
```
Вторая проверяет вложенный объект:
```text
$.payload
```
В обоих случаях:
- объект обязан быть Mapping;
- каждый ключ обязан иметь тип `str`.
Подобный подход полностью совпадает с реализацией Quote и OHLC.
---
# Использование MappingProxyType
После успешной проверки содержимое
```text
payload
```
копируется в
```python
MappingProxyType(dict(payload))
```
Таким образом создаётся неизменяемое представление транспортного документа.
Использование `MappingProxyType` решает сразу несколько задач.
Во-первых, предотвращается случайное изменение данных после завершения Schema Validation.
Во-вторых, исключается влияние внешнего кода на результаты проверки структуры.
В-третьих, последующие уровни Pipeline получают гарантированно неизменяемый документ.
Parser, Value Validation и Mapper могут безопасно использовать полученные данные, не опасаясь их изменения между этапами обработки.
---
# Почему не используется транспортная модель
Build 060.10 принципиально не создаёт экземпляр
```text
DzengiWebSocketTradeEvent
```
Это является обязанностью Parser.
Schema Validation лишь подтверждает корректность структуры сообщения.
Создание транспортной модели переносится на следующий Build.
Подобное разделение ответственности уже используется в существующих WebSocket-конвейерах Quote и OHLC.
---
# Граница ответственности Build
Build 060.10 отвечает исключительно за структурную корректность документа.
В его обязанности входит:
- проверка структуры корневого объекта;
- проверка транспортной оболочки;
- проверка структуры payload;
- проверка обязательных полей;
- формирование неизменяемого документа Validation.
Build **не выполняет**:
- Parsing;
- преобразование JSON в транспортную модель;
- преобразование типов;
- Decimal-конвертацию;
- проверку диапазонов;
- проверку timestamp;
- проверку символа;
- проверку стороны сделки;
- Mapping;
- создание канонической модели `Trade`.
Каждая из перечисленных задач относится к отдельному архитектурному уровню и будет реализована в следующих Build.
---
# Использование TradeSchemaError
Для всех ошибок структуры используется уже существующее исключение
```text
TradeSchemaError
```
Build не вводит новых типов исключений.
Это сохраняет единый подход ко всей подсистеме Validation и полностью соответствует существующей архитектуре обработки ошибок.
---
# Целевой конвейер обработки WebSocket Trade
После завершения Build 060.10 конвейер обработки принимает следующий вид.
```text
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 реализуют два различных архитектурных уровня.
```text
Build 060.9
```
вводит транспортную модель
```text
DzengiWebSocketTradeEvent
```
которая описывает уже разобранное WebSocket-событие.
```text
Build 060.10
```
вводит документ
```text
ValidatedWebSocketTradeDocument
```
который представляет собой результат проверки структуры исходного JSON-документа.
Таким образом последовательность обработки становится следующей.
```text
Raw JSON
ValidatedWebSocketTradeDocument
DzengiWebSocketTradeEvent
Trade
```
Каждый объект относится к собственному архитектурному уровню и не дублирует ответственность другого.
---
# Изменённые файлы
В рамках Build были изменены только два файла.
## Schema Validation
```text
src/market_data/acquisition/validation/schema.py
```
Добавлены:
```text
ValidatedWebSocketTradeDocument
validate_dzengi_websocket_trade_schema(...)
_validate_websocket_trade_payload(...)
_require_websocket_trade_mapping(...)
```
При этом существующие валидаторы Quote и OHLC, импорты и поведение файла не изменялись.
---
## Unit-тесты
```text
tests/unit/market_data/acquisition/validation/test_websocket_trade_schema.py
```
Добавлен полный набор unit-тестов нового уровня Schema Validation.
---
# Добавленные тесты
В рамках Build реализовано двадцать unit-тестов, полностью покрывающих функциональность нового валидатора.
## Проверка успешной валидации
Тест
```text
test_validate_websocket_trade_schema_returns_immutable_document
```
проверяет:
- успешную проверку корректного документа;
- создание `ValidatedWebSocketTradeDocument`;
- использование `MappingProxyType`;
- сохранение обязательных полей.
---
## Проверка correlationId
Тест
```text
test_validate_websocket_trade_schema_preserves_correlation_id
```
подтверждает корректное сохранение необязательного поля
`correlationId`.
---
## Проверка копирования payload
Тест
```text
test_validate_websocket_trade_schema_copies_payload
```
подтверждает, что изменения исходного словаря после Validation
не влияют на содержимое результирующего документа.
---
## Проверка структуры корневого объекта
Тест
```text
test_validate_websocket_trade_schema_rejects_non_mapping_root
```
подтверждает генерацию `TradeSchemaError`,
если корневой объект не является JSON Mapping.
---
## Проверка обязательных полей транспортной оболочки
Параметризованный тест
```text
test_validate_websocket_trade_schema_rejects_missing_root_field
```
проверяет отсутствие:
- status;
- destination;
- payload.
---
## Проверка структуры payload
Тест
```text
test_validate_websocket_trade_schema_rejects_non_mapping_payload
```
проверяет, что поле `payload`
обязано быть JSON Mapping.
---
## Проверка обязательных полей Trade
Параметризованный тест
```text
test_validate_websocket_trade_schema_rejects_missing_payload_field
```
проверяет отсутствие каждого обязательного элемента:
- id;
- price;
- size;
- ts;
- symbol;
- buyer;
- orderId.
---
## Проверка сообщения об ошибке
Тест
```text
test_validate_websocket_trade_schema_reports_all_missing_fields
```
подтверждает,
что исключение содержит полный список отсутствующих полей.
---
## Отсутствие проверки значений
Тест
```text
test_validate_websocket_trade_schema_does_not_validate_values
```
подтверждает архитектурный принцип Build.
Schema Validation проверяет исключительно структуру
и принципиально не анализирует содержимое полей.
---
## Дополнительные поля
Тест
```text
test_validate_websocket_trade_schema_allows_additional_fields
```
подтверждает,
что неподтверждённые Production поля
не вызывают ошибку Validation.
В частности проверяется возможность присутствия
```text
clientOrderId
```
и других дополнительных элементов.
---
## Проверка строковых ключей
Реализованы отдельные тесты проверки строковых ключей
для:
- корневого объекта;
- объекта payload.
Это полностью соответствует архитектуре существующих
WebSocket Schema Validation.
---
# Результаты тестирования
Выполнен целевой запуск нового набора unit-тестов.
```bash
python -m pytest \
tests/unit/market_data/acquisition/validation/test_websocket_trade_schema.py \
-q
```
Результат:
```text
20 passed in 0.02s
```
Все проверки новой функциональности успешно завершены.
---
# Регрессионное тестирование
После завершения реализации выполнен полный запуск
подсистемы Validation.
```bash
python -m pytest \
tests/unit/market_data/acquisition/validation \
-q
```
Результат:
```text
302 passed in 0.10s
```
Регрессий существующей функциональности не обнаружено.
---
# Проверка компиляции
Выполнена проверка компиляции изменённых файлов.
```bash
python -m compileall \
src/market_data/acquisition/validation/schema.py \
tests/unit/market_data/acquisition/validation/test_websocket_trade_schema.py
```
Компиляция завершилась успешно.
Синтаксические ошибки отсутствуют.
---
# Проверка Git diff
Выполнена финальная проверка изменений.
```bash
git diff --check
```
Ошибок не обнаружено.
Это подтверждает отсутствие:
- trailing whitespace;
- конфликтов окончания строк;
- ошибок форматирования diff.
---
# Scope Build 060.10
В рамках данного Build реализовано только:
```text
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-событий.
```text
Quote
Raw WebSocket
Schema Validation
ValidatedWebSocketQuoteDocument
OHLC
Raw WebSocket
Schema Validation
ValidatedWebSocketOhlcDocument
Trade
Raw WebSocket
Schema Validation
ValidatedWebSocketTradeDocument
```
Архитектура стала полностью симметричной.
---
# Состояние WebSocket Trade Pipeline
После завершения Build 060.10 конвейер имеет следующий вид.
```text
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.
---
# Следующий этап
Следующим этапом дорожной карты является
```text
Build 060.11 — WebSocket Trade Parser
```
Цель Build:
- преобразование `ValidatedWebSocketTradeDocument`;
- создание транспортной модели `DzengiWebSocketTradeEvent`;
- нормализация имён транспортных полей;
- преобразование JSON-ключей:
- `id → trade_id`;
- `ts → timestamp`;
- `orderId → order_id`;
- сохранение исходных числовых значений без преобразования типов;
- отсутствие Value Validation.
После завершения Build 060.11 конвейер примет следующий вид:
```text
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**.