Files
dzentra_bot/docs/migrations/build_059_12.md

588 lines
13 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 059.12 — Runtime Event Models
**Migration Build**
---
# Цель Build
После завершения Build 059.11 Runtime уже содержит три независимых архитектурных уровня:
- Runtime Protocols;
- Runtime Transport Messages;
- Runtime Commands.
Следующим шагом является создание слоя **Runtime Events**.
Данный Build вводит immutable-модели событий Runtime.
События описывают **уже произошедшие факты** и полностью отделены от команд Runtime.
---
# Причина появления Runtime Events
До настоящего момента Runtime умел описывать:
- транспортные интерфейсы;
- транспортные сообщения;
- намерения системы.
Однако отсутствовал механизм описания результатов выполнения этих намерений.
Например.
После выполнения
```
ConnectCommand
```
может произойти:
```
ConnectedEvent
```
или
```
ConnectFailedEvent
```
Это два разных факта.
Команда выражает желание выполнить действие.
Событие фиксирует результат выполнения этого действия.
---
# Архитектурная идея
Build 059.12 завершает построение базовой event-driven модели Runtime.
Получается следующая архитектура.
```text
Runtime
Commands
Session
Transport
Events
```
Commands направляются вниз.
Events распространяются вверх.
Именно такое разделение используется в большинстве современных event-driven систем.
---
# Новый модуль
Создан файл
```
src/market_data/acquisition/runtime/runtime_events.py
```
В модуле определены immutable-модели Runtime Events.
---
# Использование Transport Messages
Транспортные события используют модели Build 059.10.
```
TransportTextMessage
TransportBinaryMessage
```
Runtime Event не знает содержимого сообщения.
Он лишь фиксирует факт передачи или получения транспортного payload.
---
# TransportMessage
Для удобства типизации используется локальный alias.
```python
TransportMessage =
TransportTextMessage
| TransportBinaryMessage
```
Он используется только внутри Runtime Events.
Никакой новой модели данных не создаётся.
---
# Новые события
Build вводит девять Runtime Events.
---
# ConnectedEvent
Фиксирует успешное открытие транспортного соединения.
Событие является маркерным.
Не содержит дополнительных данных.
Причина.
На текущем этапе Runtime отсутствует модель идентификатора соединения.
Добавлять подобные поля преждевременно.
---
# DisconnectedEvent
Фиксирует завершение транспортного соединения.
Событие также является маркерным.
Причина отключения намеренно отсутствует.
Определение причин разрыва соединения относится к будущему уровню Reliability.
---
# ConnectFailedEvent
Фиксирует неудачную попытку подключения.
Содержит:
```
reason
```
Причина хранится в виде строки.
---
## Почему используется строка
Во время проектирования рассматривались варианты хранения:
- Exception;
- traceback;
- transport-specific error;
- websocket exception.
От данных вариантов было принято решение отказаться.
Runtime Event не должен зависеть от конкретной реализации транспорта.
Строковое описание полностью соответствует принципу transport-agnostic Runtime.
---
# MessageReceivedEvent
Фиксирует получение транспортного сообщения.
Содержит:
```
TransportMessage
```
Runtime Event не анализирует payload.
Его обработкой занимаются последующие уровни Acquisition.
---
# MessageSentEvent
Фиксирует успешную передачу транспортного сообщения.
Содержит:
```
TransportMessage
```
Это позволяет журналировать транспортный обмен, не анализируя содержимое сообщений.
---
# ReconnectStartedEvent
Фиксирует начало новой попытки восстановления соединения.
Содержит:
```
attempt
```
---
## Почему хранится номер попытки
Номер попытки является устойчивым Runtime-фактом.
Он потребуется:
- Supervisor;
- журналированию;
- диагностике;
- мониторингу Runtime.
---
# ReconnectCompletedEvent
Фиксирует успешное восстановление соединения.
Также содержит:
```
attempt
```
что позволяет определить, на какой попытке произошло восстановление.
---
# ReconnectFailedEvent
Фиксирует завершение очередной попытки восстановления соединения с ошибкой.
Содержит:
```
attempt
reason
```
Таким образом Runtime может описывать процесс восстановления без зависимости от конкретной реализации транспорта.
---
# HeartbeatTimeoutEvent
Фиксирует превышение допустимого интервала heartbeat.
Содержит:
```
timeout_seconds
```
Хранится только настроенный порог ожидания.
---
## Почему отсутствуют timestamp
Во время проектирования обсуждалось хранение:
```
timestamp
occurred_at
created_at
```
Было принято решение отказаться.
Причины.
---
### Причина №1
В Runtime ещё отсутствует единая модель времени.
---
### Причина №2
В разных окружениях время может поступать из различных источников.
Например:
- системные часы;
- монотонные часы;
- серверное время биржи.
До появления общей модели времени вводить timestamp преждевременно.
---
# Почему отсутствует RuntimeEvent
Также обсуждалось создание общего базового класса.
Например.
```
RuntimeEvent
```
или
```
BaseEvent
```
От идеи отказались.
Причины.
---
## Причина №1
Все события являются immutable dataclass.
Общего поведения между ними нет.
---
## Причина №2
Преждевременная иерархия только усложняет архитектуру.
---
## Причина №3
Общий базовый тип можно добавить позднее без нарушения обратной совместимости.
---
# Почему отсутствует RuntimeEventType
Рассматривалось использование enum.
Например.
```
CONNECTED
DISCONNECTED
MESSAGE_RECEIVED
```
Было принято решение отказаться.
Тип события полностью определяется его классом.
Дополнительный enum создавал бы дублирование информации.
---
# Почему отсутствуют Subscription Events
Изначально предполагалось добавить:
- SubscriptionRegisteredEvent;
- SubscriptionRemovedEvent;
- SubscriptionRestoredEvent.
После анализа архитектуры было принято решение перенести их в следующий Build.
Причина.
В Build 059.12 Subscription Manager ещё отсутствует.
Следовательно, пока отсутствует компонент, способный генерировать подобные события.
События должны появляться одновременно с соответствующим уровнем архитектуры.
Поэтому Subscription Events перенесены в Build 059.13.
---
# Что НЕ входит в Build
Сознательно не реализованы:
- Event Bus;
- Dispatcher;
- Observer;
- callbacks;
- asyncio;
- Publisher;
- Subscriber;
- Session;
- Subscription Manager;
- обработчики событий;
- очередь событий.
Build содержит исключительно immutable-модели Runtime Events.
---
# Обновлённая архитектура Runtime
После завершения Build Runtime приобретает следующий вид.
```text
Runtime
Protocols
Transport Messages
Runtime Commands
Runtime Events
Transport
Network
```
Каждый уровень отвечает только за собственную область ответственности.
---
# Следующие Build
## Build 059.13
Subscription Manager.
Появятся:
- управление подписками;
- хранение Runtime-состояния;
- восстановление подписок;
- SubscriptionRegisteredEvent;
- SubscriptionRemovedEvent;
- SubscriptionRestoredEvent.
---
## Build 059.14
WebSocket Session.
Появится координация:
- Commands;
- Events;
- Transport;
- Subscription Manager.
---
## Build 059.15
Runtime Reliability.
Будут реализованы:
- Heartbeat;
- Reconnect;
- Supervisor;
- Scheduler;
- Ping/Pong.
---
# Проверка Build
Выполнена полная проверка.
---
## Компиляция
```
python -m compileall
```
Успешно.
---
## Unit Tests
Созданы тесты:
```
test_runtime_events.py
```
Проверяется:
- создание каждого события;
- корректность хранения данных;
- поддержка TransportMessage;
- immutable-поведение dataclass.
Все тесты успешно пройдены.
---
## Runtime Regression
Совместно проверены:
- Runtime Protocols;
- Runtime Transport Messages;
- Runtime Commands;
- Runtime Events.
Все Runtime-тесты успешно завершены.
---
## Проверка репозитория
Выполнен
```
git diff --check
```
Ошибок форматирования не обнаружено.
---
# Итог
Build 059.12 завершает формирование слоя Runtime Events.
Теперь Runtime имеет четыре полностью независимых уровня.
```text
Protocols
Transport Messages
Runtime Commands
Runtime Events
```
Каждый уровень описывает собственную область ответственности.
Commands выражают намерения системы.
Events фиксируют уже произошедшие факты.
Подобное разделение делает архитектуру Runtime предсказуемой, расширяемой и соответствует общепринятым принципам построения event-driven систем.
Следующий Build посвящён созданию Subscription Manager, который станет первым Runtime-компонентом, использующим одновременно Commands и Events, сохраняя при этом независимость транспортного уровня от бизнес-логики Acquisition.