build 059.12: add runtime event models
This commit is contained in:
588
docs/migrations/build_059_12.md
Normal file
588
docs/migrations/build_059_12.md
Normal file
@@ -0,0 +1,588 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user