420 lines
14 KiB
Markdown
420 lines
14 KiB
Markdown
# Build 060.25 — Production Runtime Integration
|
||
|
||
**Engineering Migration Report**
|
||
|
||
---
|
||
|
||
## Контроль документа
|
||
|
||
| Свойство | Значение |
|
||
|---|---|
|
||
| Build | 060.25 |
|
||
| Статус | Completed |
|
||
| Подсистема | Market Data Acquisition |
|
||
| Компонент | Trades Feed / Trade Stream Runtime |
|
||
| Дата завершения | 2026-07-31 |
|
||
| Версия | 1.0 |
|
||
|
||
---
|
||
|
||
## Связанные документы
|
||
|
||
- `build_060_24.md` — итог внутренней Runtime Recovery Architecture;
|
||
- `build_060_24_architecture.md` — архитектурные границы Recovery Runtime;
|
||
- `build_060_25_architecture.md` — полная спецификация Production Runtime
|
||
Integration и принятые ADR;
|
||
- `dzentra_target_architecture.md` — место Trade Stream в целевой
|
||
архитектуре Dzentra;
|
||
- `master-roadmap.md` — дальнейшая последовательность Build.
|
||
|
||
---
|
||
|
||
## 1. Назначение Build
|
||
|
||
Build 060.24 создал внутренний граф компонентов Trade Stream Runtime,
|
||
но не подключал его к реальному жизненному циклу приложения.
|
||
|
||
Цель Build 060.25 — превратить этот граф в один управляемый production
|
||
Runtime:
|
||
|
||
```text
|
||
Application Bootstrap
|
||
│
|
||
▼
|
||
Production Trade Stream Factory
|
||
│
|
||
▼
|
||
WebSocket connect and subscribe
|
||
│
|
||
▼
|
||
Trade receive loop
|
||
│
|
||
├── ACK / control routing
|
||
├── Canonical Trade pipeline
|
||
├── Consistency checkpoint
|
||
└── Runtime Events
|
||
│
|
||
▼
|
||
Heartbeat / Supervisor / Scheduler
|
||
│
|
||
▼
|
||
reconnect → subscription restore → recovery
|
||
│
|
||
▼
|
||
resume buffered live processing
|
||
```
|
||
|
||
Build сохраняет границы Transport, Acquisition, Consistency, Recovery
|
||
и Runtime. Внешний WebSocket документ становится Canonical Trade только
|
||
после прохождения существующего Acquisition pipeline.
|
||
|
||
---
|
||
|
||
## 2. Завершённые подэтапы
|
||
|
||
| Подэтап | Название | Статус |
|
||
|---|---|---|
|
||
| 060.25.0 | Static Contract Cleanup | Accepted |
|
||
| 060.25.1 | Dzengi WebSocket Transport | Accepted |
|
||
| 060.25.2 | WebSocket Session and Subscription Manager | Accepted |
|
||
| 060.25.3 | Async Runtime Event Publisher | Accepted |
|
||
| 060.25.4 | Trade Stream Production Runtime | Accepted |
|
||
| 060.25.5 | Reconnect and Recovery Integration | Accepted |
|
||
| 060.25.6 | Heartbeat and Scheduler Integration | Accepted |
|
||
| 060.25.7 | Settings, Bootstrap and Graceful Shutdown | Accepted |
|
||
| 060.25.8 | Targeted Runtime Verification | Accepted |
|
||
|
||
Каждый подэтап прошёл отдельный архитектурный review. Обнаруженные
|
||
findings исправлялись до принятия соответствующего этапа.
|
||
|
||
---
|
||
|
||
## 3. Итоговая ответственность компонентов
|
||
|
||
### DzengiWebSocketTransport
|
||
|
||
- открывает и закрывает WebSocket connection;
|
||
- отправляет и получает только `str | bytes`;
|
||
- выполняет конечный Ping/Pong liveness probe;
|
||
- не знает JSON, Trade, подписки и Recovery;
|
||
- использует отключённый встроенный WebSocket keepalive.
|
||
|
||
### WebSocketSession
|
||
|
||
- идемпотентно запускает и останавливает Transport;
|
||
- повторный `start()` не заменяет исправное OPEN-соединение;
|
||
- принудительная замена выполняется только явным reconnect.
|
||
|
||
### WebSocketSubscriptionManager
|
||
|
||
- разделяет желаемые и фактически активные подписки;
|
||
- сохраняет намерение подписаться после временной ошибки send;
|
||
- восстанавливает подписки после reconnect;
|
||
- не имитирует неподдерживаемый Dzengi unsubscribe.
|
||
|
||
### Async Runtime Event Publisher
|
||
|
||
- последовательно и с `await` доставляет событие всем Consumer;
|
||
- не создаёт скрытых background tasks;
|
||
- изолирует обычную ошибку Consumer от Runtime lifecycle;
|
||
- распространяет cancellation;
|
||
- защищён от прямой и child-task reentrancy;
|
||
- не включает чувствительный payload в аварийную диагностику.
|
||
|
||
### TradeStreamProductionRuntime
|
||
|
||
- является единственным владельцем startup, receive и Scheduler tasks;
|
||
- маршрутизирует control и market сообщения;
|
||
- передаёт Trade document в общий Acquisition/Consistency pipeline;
|
||
- связывает transport failure с reconnect и Recovery;
|
||
- выполняет полный cleanup при остановке, ошибке и cancellation.
|
||
|
||
### RuntimeReconnectRecoveryCoordinator
|
||
|
||
- обеспечивает single-flight для одного поколения соединения;
|
||
- закрывает общий live-processing gate;
|
||
- выполняет reconnect;
|
||
- восстанавливает подписки;
|
||
- запускает REST Recovery вне event loop;
|
||
- открывает live processing только после завершения Recovery;
|
||
- оставляет gate в failed state после terminal Recovery error.
|
||
|
||
### Heartbeat, Supervisor и Scheduler
|
||
|
||
- используют состояние Transport, а не частоту рыночных сделок;
|
||
- выполняют Ping/Pong с конечным timeout;
|
||
- объединяют одновременные heartbeat и receive failures в одну
|
||
reconnect/recovery operation;
|
||
- создают ровно одну Scheduler task;
|
||
- останавливаются в порядке Scheduler → Supervisor → receive loop.
|
||
|
||
### Application Runner
|
||
|
||
- владеет Telegram polling и опциональным Trade Stream Runtime;
|
||
- считает ошибку включённого Trade Stream фатальной;
|
||
- ожидает завершение обеих корневых задач;
|
||
- не позволяет повторной cancellation прервать cleanup;
|
||
- закрывает Bot session ровно один раз.
|
||
|
||
---
|
||
|
||
## 4. Production lifecycle
|
||
|
||
### Запуск
|
||
|
||
```text
|
||
load settings
|
||
↓
|
||
feature flag disabled
|
||
└── Runtime graph не создаётся
|
||
|
||
feature flag enabled
|
||
↓
|
||
build concrete dependency graph
|
||
↓
|
||
start WebSocket session
|
||
↓
|
||
send Trade subscription
|
||
↓
|
||
start Supervisor
|
||
↓
|
||
start receive loop and Scheduler
|
||
```
|
||
|
||
Фабрика только собирает граф зависимостей. Сетевые действия начинаются
|
||
только из `TradeStreamProductionRuntime.run()`.
|
||
|
||
### Reconnect и Recovery
|
||
|
||
```text
|
||
transport failure or failed liveness probe
|
||
↓
|
||
capture connection generation
|
||
↓
|
||
acquire single-flight operation
|
||
↓
|
||
close live-processing gate
|
||
↓
|
||
disconnect old connection
|
||
↓
|
||
connect new connection
|
||
↓
|
||
restore desired subscriptions
|
||
↓
|
||
recover missing Trades through REST
|
||
↓
|
||
process buffered live Trades
|
||
```
|
||
|
||
Recovery и live processing используют один экземпляр Consistency Layer
|
||
и не изменяют checkpoint параллельно.
|
||
|
||
### Остановка
|
||
|
||
```text
|
||
stop Scheduler
|
||
↓
|
||
await Scheduler task
|
||
↓
|
||
stop Supervisor
|
||
↓
|
||
cancel and await receive loop
|
||
↓
|
||
stop WebSocket session
|
||
↓
|
||
clear subscriptions
|
||
↓
|
||
close Bot session at Application boundary
|
||
```
|
||
|
||
---
|
||
|
||
## 5. Конфигурация
|
||
|
||
Trade Stream управляется отдельным безопасным feature flag:
|
||
|
||
```text
|
||
TRADE_STREAM_ENABLED
|
||
```
|
||
|
||
При включённом Runtime обязательны явные:
|
||
|
||
- WebSocket URL;
|
||
- список символов;
|
||
- transport timeouts;
|
||
- heartbeat timeout;
|
||
- Scheduler interval;
|
||
- максимальный размер Recovery Window.
|
||
|
||
Legacy WebSocket URL и `default_symbol` не используются как fallback.
|
||
Наличие `EXCHANGE_ENABLED` само по себе не включает Trade Stream.
|
||
|
||
---
|
||
|
||
## 6. Ключевые архитектурные гарантии
|
||
|
||
После Build 060.25 выполняются следующие правила:
|
||
|
||
```text
|
||
exactly one production receive loop
|
||
```
|
||
|
||
```text
|
||
exactly one scheduler task
|
||
```
|
||
|
||
```text
|
||
at most one reconnect/recovery sequence per generation
|
||
```
|
||
|
||
```text
|
||
reconnect =
|
||
disconnect
|
||
→ connect
|
||
→ restore subscriptions
|
||
```
|
||
|
||
```text
|
||
recovery precedes buffered live processing
|
||
```
|
||
|
||
```text
|
||
disabled Trade Stream creates no Runtime graph
|
||
```
|
||
|
||
```text
|
||
construction has no network side effects
|
||
```
|
||
|
||
```text
|
||
all owned tasks are cancelled or completed and awaited
|
||
```
|
||
|
||
---
|
||
|
||
## 7. Реализованные файлы
|
||
|
||
### Добавленные production-файлы
|
||
|
||
```text
|
||
app/src/bootstrap/
|
||
application.py
|
||
trade_stream_runtime.py
|
||
|
||
app/src/market_data/acquisition/adapters/dzengi/
|
||
websocket_control_message_handler.py
|
||
websocket_inbound_message_classifier.py
|
||
websocket_transport.py
|
||
|
||
app/src/market_data/acquisition/runtime/
|
||
acquisition_runtime_event_logging_consumer.py
|
||
acquisition_runtime_event_publisher.py
|
||
live_processing_gate.py
|
||
runtime_liveness_probe.py
|
||
runtime_reconnect_recovery_coordinator.py
|
||
trade_stream_production_runtime.py
|
||
websocket_inbound_message.py
|
||
websocket_session.py
|
||
websocket_subscription_manager.py
|
||
```
|
||
|
||
### Изменённые production-файлы
|
||
|
||
```text
|
||
app/.env.example
|
||
app/src/bootstrap/app_factory.py
|
||
app/src/core/config.py
|
||
app/src/integrations/exchange/rest_client.py
|
||
app/src/main.py
|
||
app/src/market_data/acquisition/exceptions.py
|
||
app/src/market_data/acquisition/runtime/reconnect.py
|
||
app/src/market_data/acquisition/runtime/scheduler.py
|
||
app/src/market_data/acquisition/runtime/supervisor.py
|
||
app/src/market_data/acquisition/trade_stream_runtime_composition.py
|
||
```
|
||
|
||
### Тесты
|
||
|
||
Добавлено или расширено покрытие:
|
||
|
||
```text
|
||
app/tests/unit/bootstrap/
|
||
app/tests/unit/core/
|
||
app/tests/unit/market_data/acquisition/adapters/dzengi/
|
||
app/tests/unit/market_data/acquisition/runtime/
|
||
app/tests/unit/market_data/acquisition/
|
||
app/tests/unit/test_main.py
|
||
```
|
||
|
||
Постороннее пользовательское изменение `.gitignore` не относится к
|
||
Build 060.25.
|
||
|
||
---
|
||
|
||
## 8. Targeted Runtime Verification
|
||
|
||
060.25.8 добавил только тестовый код и не менял production-поведение.
|
||
|
||
Через реальную production factory и реальные компоненты Runtime graph,
|
||
но с управляемыми WebSocket и REST boundaries, проверены:
|
||
|
||
1. выключенный feature flag не создаёт Runtime graph;
|
||
2. subscribe → ACK → Trade обновляет общий checkpoint;
|
||
3. ошибка connect фатальна и не оставляет задач;
|
||
4. ошибка первой subscription send полностью откатывает startup;
|
||
5. reconnect заменяет connection и восстанавливает подписку до Recovery;
|
||
6. recovered Trade обрабатывается раньше buffered live Trade;
|
||
7. Recovery error запрещает обработку buffered live Trade;
|
||
8. одновременные ошибки корневых задач наблюдаются детерминированно;
|
||
9. повторная cancellation не прерывает cleanup;
|
||
10. Bot session закрывается один раз, owned tasks всегда await-ятся.
|
||
|
||
Итоговый read-only review 060.25.8 новых findings не выявил.
|
||
|
||
---
|
||
|
||
## 9. Результаты тестирования
|
||
|
||
Повторная проверка выполнена 2026-07-31:
|
||
|
||
```text
|
||
Expanded Production Runtime target: 445 passed
|
||
Full project regression: 1869 passed
|
||
```
|
||
|
||
Тесты не используют реальную сеть, production credentials или
|
||
недетерминированные внешние задержки.
|
||
|
||
---
|
||
|
||
## 10. Что не входит в Build
|
||
|
||
Build 060.25 не реализует:
|
||
|
||
- длительные live exchange и network fault scenarios;
|
||
- production stress certification;
|
||
- persistent market data storage;
|
||
- persistent checkpoint;
|
||
- startup recovery после перезапуска процесса;
|
||
- historical query и Replay API;
|
||
- аналитические вычисления поверх исторических данных.
|
||
|
||
Эти задачи относятся к следующим Build и зафиксированы в
|
||
`master-roadmap.md`.
|
||
|
||
---
|
||
|
||
## 11. Итог
|
||
|
||
Build 060.25 завершён.
|
||
|
||
Trade Stream подключён к bootstrap приложения как отдельный,
|
||
отключённый по умолчанию production Runtime. Он управляет реальным
|
||
WebSocket lifecycle, восстанавливает подписки и пропущенные сделки,
|
||
сохраняет порядок Recovery и Live processing и детерминированно
|
||
освобождает принадлежащие ему ресурсы.
|
||
|
||
Следующий этап — Build 060.26, посвящённый интеграционным, fault,
|
||
reconnect, recovery и stress-сценариям за пределами детерминированного
|
||
in-process unit harness.
|