# 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.