Files
dzentra_bot/docs/migrations/build_060_25.md

423 lines
14 KiB
Markdown
Raw Permalink 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.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 Engineering Migration Report](build_060_24.md) — итог
внутренней Runtime Recovery Architecture;
- [Build 060.24 Architecture](build_060_24_architecture.md) —
архитектурные границы Recovery Runtime;
- [Build 060.25 Architecture](build_060_25_architecture.md) — полная
спецификация Production Runtime Integration и принятые ADR;
- [Dzentra Target Architecture](../architecture/dzentra_target_architecture.md) —
место Trade Stream в целевой архитектуре Dzentra;
- [Master Roadmap](../roadmap/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](build_060_26.md), посвящённый
интеграционным, fault, reconnect, recovery и stress-сценариям за
пределами детерминированного in-process unit harness.