build 059.12: add runtime event models

This commit is contained in:
2026-07-17 20:19:00 +03:00
parent d2d8f8fad4
commit f2bacb80c9
3 changed files with 818 additions and 0 deletions

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