Files
dzentra_bot/docs/migrations/build_060_22_architecture.md

40 KiB
Raw Permalink Blame History

Build 060.22 — Acquisition Runtime Service

Статус: Accepted

Тип документа: Architecture Specification

Build: 060.22
Ветка: Trades Feed (Time & Sales)
Документ: build_060_22_architecture.md
Связанные документы:


Назначение документа

Настоящий документ является официальной архитектурной спецификацией Build 060.22 — Acquisition Runtime Service.

Документ определяет создание первого исполняемого сервисного компонента Runtime Layer подсистемы Market Data Acquisition.

Build 060.21 сформировал типизированную контрактную границу Runtime:

AcquisitionRuntimeCommand

AcquisitionRuntimeEvent

AcquisitionRuntimeCommandDispatcherProtocol

AcquisitionRuntimeEventPublisherProtocol

Однако созданные контракты пока не имеют производственной реализации.

В системе отсутствует компонент, который:

  • принимает типизированные Runtime-команды;
  • маршрутизирует их к соответствующим инфраструктурным зависимостям;
  • публикует результирующие Runtime-события;
  • формирует единую точку исполнения команд Acquisition Runtime.

Build 060.22 закрывает именно эту архитектурную задачу.

Документ служит единственным источником истины при реализации данного Build.

Изменение зафиксированных решений в процессе написания кода не допускается без отдельного архитектурного пересмотра.


Статус Build

Build 060.22 является следующим этапом серии Build 060, посвящённой формированию полноценной подсистемы Trades Feed (Time & Sales).

К моменту начала данного Build в проекте уже существуют:

  • транспортные модели WebSocket;
  • Runtime Commands;
  • Runtime Events;
  • WebSocket transport protocol;
  • WebSocket session protocol;
  • WebSocket subscription manager protocol;
  • контракт диспетчеризации Runtime-команд;
  • контракт публикации Runtime-событий;
  • Canonical Trade Model;
  • Trades Feed;
  • Trade Stream Consistency;
  • Trade Recovery;
  • специализированное хранилище TradeStreamStateStore.

При этом Runtime Layer пока состоит только из контрактов и моделей сообщений.

Фактический сервис исполнения Runtime-команд отсутствует.

Следовательно, Runtime ещё не является работающей подсистемой.

Build 060.22 вводит минимальную исполняемую реализацию сервисного уровня, не подключая её пока к Trades Feed и корневому Acquisition Service.


Контекст

После завершения Build 060.21 архитектура Runtime Protocol Layer выглядит следующим образом.

AcquisitionRuntimeCommand
            │
            ▼
AcquisitionRuntimeCommandDispatcherProtocol

и:

AcquisitionRuntimeEvent
            │
            ▼
AcquisitionRuntimeEventPublisherProtocol

Контракты определяют:

  • какие команды допустимы внутри Acquisition Runtime;
  • какие события может публиковать Runtime;
  • каким образом вызывающий компонент передаёт команду;
  • каким образом инфраструктурный результат передаётся потребителям.

Однако контракт сам по себе не выполняет команду.

Например:

ConnectCommand

уже существует как типизированная команда, но в системе пока отсутствует компонент, который обязан:

ConnectCommand
        │
        ▼
WebSocketSessionProtocol.start()

Аналогично:

DisconnectCommand
        │
        ▼
WebSocketSessionProtocol.stop()

Для команд управления подписками и отправки сообщений также пока отсутствует единая точка исполнения.

Таким образом между публичным Runtime Protocol Layer и низкоуровневыми WebSocket-контрактами остаётся незаполненная сервисная граница.


Предпосылки

Настоящий Build опирается на архитектурные решения, принятые в предыдущих этапах.

Build 059.10

Сформированы базовые контракты WebSocket Runtime:

WebSocketTransportProtocol

WebSocketSessionProtocol

WebSocketSubscriptionManagerProtocol

Данные контракты описывают отдельные инфраструктурные возможности, но не объединяют их в единый сервис исполнения команд.


Build 059.11059.12

Сформированы транспортные команды и события Runtime.

Появились типизированные модели:

ConnectCommand

DisconnectCommand

SubscribeCommand

UnsubscribeCommand

SendTextCommand

SendBinaryCommand

а также соответствующие инфраструктурные события.


Build 060.18

Создана подсистема Trade Stream Consistency.

Она полностью независима от Runtime Transport и принимает только канонические объекты Trade.


Build 060.19

Создана подсистема Trade Recovery.

Recovery остаётся stateless и зависит только от:

TradeStreamConsistencyProtocol

Build 060.20.1

Владение состоянием Trade Stream перенесено в:

TradeStreamStateStore

Runtime Transport окончательно перестал рассматриваться как владелец состояния предметной области.


Build 060.21

Сформирован интеграционный контракт Runtime Protocol Layer.

Добавлены:

AcquisitionRuntimeCommand

AcquisitionRuntimeEvent

AcquisitionRuntimeCommandDispatcherProtocol

AcquisitionRuntimeEventPublisherProtocol

Имена были намеренно ограничены контекстом Acquisition, чтобы исключить конфликт с существующей общесистемной подсистемой:

src/runtime_events/

Build 060.21 определил границы взаимодействия, но сознательно не создавал производственную реализацию.


Проблема

В текущем состоянии каждая Runtime-команда является только неизменяемым объектом данных.

Например:

ConnectCommand()

не содержит логики подключения.

Она только выражает намерение вызывающего компонента.

То же относится к:

DisconnectCommand()
SubscribeCommand(...)
UnsubscribeCommand(...)
SendTextCommand(...)
SendBinaryCommand(...)

Для выполнения команд необходим отдельный сервис, который:

  1. принимает объект команды;
  2. определяет его конкретный тип;
  3. выбирает соответствующую инфраструктурную зависимость;
  4. выполняет строго определённую операцию;
  5. не содержит знаний о Trade, Consistency или Recovery.

Без такого компонента Runtime Protocol Layer остаётся декларативным и не может использоваться следующими уровнями системы.


Основная идея Build

Главная идея Build 060.22 заключается в создании тонкого сервиса маршрутизации Runtime-команд.

Новый компонент:

AcquisitionRuntimeService

становится производственной реализацией:

AcquisitionRuntimeCommandDispatcherProtocol

Сервис принимает типизированную команду и делегирует выполнение уже существующим инфраструктурным контрактам.

Концептуально:

AcquisitionRuntimeCommand
            │
            ▼
AcquisitionRuntimeService
            │
      ┌─────┴─────┐
      ▼           ▼
WebSocket      Subscription
Session        Manager

Сервис не реализует WebSocket самостоятельно.

Он не содержит сетевого клиента.

Он не создаёт транспорт.

Он только координирует существующие зависимости.


Цель Build

Build обязан создать единственную производственную точку исполнения типизированных Acquisition Runtime Commands.

После завершения этапа система должна обеспечивать:

  • приём всех команд из AcquisitionRuntimeCommand;
  • детерминированную маршрутизацию каждой команды;
  • делегирование lifecycle-команд WebSocket Session;
  • делегирование управления подписками Subscription Manager;
  • делегирование отправки транспортных сообщений соответствующей зависимости;
  • соответствие AcquisitionRuntimeCommandDispatcherProtocol;
  • независимое unit-тестирование без реального сетевого соединения.

Build не должен изменять поведение существующих Runtime Commands и Runtime Events.


Что НЕ входит в Scope Build

Настоящий Build сознательно не реализует:

  • интеграцию Runtime Service в корневой Acquisition Service;
  • интеграцию Runtime Service с Trades Feed;
  • Composition Root;
  • реальный WebSocket client;
  • Runtime Supervisor;
  • Reconnect Controller;
  • Heartbeat;
  • Scheduler;
  • автоматическое восстановление подписок;
  • автоматический REST Recovery после reconnect;
  • обработку входящих Trade-сообщений;
  • публикацию Canonical Trade Stream;
  • регистрацию Runtime Service в Registry;
  • общесистемную шину событий;
  • конкурентную очередь команд;
  • фоновый worker;
  • сохранение Runtime-состояния между перезапусками.

Эти задачи относятся к Build 060.23060.25 либо к отдельным последующим этапам.

Build 060.22 отвечает только за синхронную с точки зрения порядка и асинхронную с точки зрения Python API диспетчеризацию одной команды за один вызов.


Архитектурные принципы

При реализации Build 060.22 используются следующие обязательные принципы.

1. Unique File Naming

Во всём репозитории Dzentra запрещено создание нескольких файлов с одинаковым именем независимо от расположения в каталогах.

Единственное разрешённое исключение:

__init__.py

Поэтому в Build не создаются файлы:

service.py
protocol.py
exceptions.py
test_service.py

Утверждённые уникальные имена:

acquisition_runtime_service.py

acquisition_runtime_service_protocol.py

test_acquisition_runtime_service.py

Имя каждого файла должно однозначно определять его назначение без учёта родительского каталога.


2. Protocol Before Implementation

Публичный контракт Runtime Service фиксируется отдельно от его реализации.

Внешние потребители в последующих Build должны зависеть от:

AcquisitionRuntimeServiceProtocol

а не от конкретного класса:

AcquisitionRuntimeService

3. Thin Application Service

Runtime Service является тонким координатором.

Он:

  • принимает команду;
  • определяет её тип;
  • делегирует операцию;
  • завершает вызов.

Сервис не переносит в себя логику нижележащих компонентов.


4. No Domain Knowledge

Runtime Service не должен импортировать:

Trade
TradeStreamConsistencyProtocol
TradeRecoveryProtocol
TradesFeed
TradeStreamStateStore

Он работает исключительно с транспортными командами и инфраструктурными контрактами.


5. Dependency Injection

Все зависимости передаются в конструктор.

Сервис не создаёт самостоятельно:

  • WebSocket Session;
  • Transport;
  • Subscription Manager;
  • Publisher;
  • Adapter.

Создание графа зависимостей относится к Composition Root и не входит в Scope Build.


6. One Command — One Deterministic Route

Каждый тип команды должен иметь ровно один допустимый маршрут исполнения.

Команда не может быть обработана несколькими зависимостями одновременно, если это отдельно не определено спецификацией.


7. No Premature Orchestration

Runtime Service не является Supervisor.

Он не запускает фоновые задачи.

Не выполняет retries.

Не планирует reconnect.

Не контролирует heartbeat.

Перечисленные обязанности появятся в специализированных компонентах позднее.


8. Existing Contracts Remain Stable

Build не изменяет публичные модели:

runtime_commands.py
runtime_events.py
transport_messages.py
websocket_protocol.py

Если реализация обнаружит недостаточность существующего контракта, изменение должно быть отдельно согласовано до внесения в код.


Acquisition Runtime Service

Назначение

AcquisitionRuntimeService является первым исполняемым компонентом Runtime Layer.

Его единственная задача — выполнение типизированных инфраструктурных Runtime-команд.

Сервис не содержит собственной бизнес-логики.

Он выполняет только маршрутизацию команд к уже существующим инфраструктурным зависимостям.

Концептуально:

Runtime Command
        │
        ▼
AcquisitionRuntimeService
        │
        ├──────────────► WebSocketSession
        │
        ├──────────────► WebSocketTransport
        │
        └──────────────► SubscriptionManager

Таким образом сервис становится единственной производственной точкой исполнения Runtime-команд.


Почему появляется отдельный Service

Во время проектирования были рассмотрены несколько вариантов.


Вариант №1

Каждый вызывающий компонент самостоятельно выполняет команды.

Например:

TradesFeed

↓

if ConnectCommand

↓

session.start()

Отклонён.

Причины:

  • дублирование логики;
  • нарушение принципа единственной ответственности;
  • отсутствие единой точки маршрутизации.

Вариант №2

Перенести выполнение команд внутрь WebSocketSession.

Например:

session.dispatch(command)

Отклонён.

Причины:

Session начинает знать о:

  • Subscription;
  • Transport;
  • Runtime Commands.

Тем самым нарушается разделение обязанностей.


Вариант №3

Создать специализированный Runtime Service.

Принят.

Именно Runtime Service становится единственным компонентом, который понимает соответствие между:

Runtime Command

↓

Infrastructure Action

Граница ответственности

Runtime Service отвечает исключительно за выполнение Runtime-команд.

Он НЕ отвечает за:

  • сетевой протокол;
  • обработку сообщений;
  • Consistency;
  • Recovery;
  • Trades Feed;
  • управление жизненным циклом приложения;
  • Supervisor;
  • Scheduler;
  • Heartbeat;
  • Reconnect.

Все перечисленные обязанности принадлежат другим Build.


AcquisitionRuntimeServiceProtocol

Назначение

Build 060.22 вводит отдельный публичный контракт сервисного уровня.

AcquisitionRuntimeServiceProtocol

Он описывает единственную публичную возможность Runtime Service.

dispatch(...)

Все последующие Build должны зависеть именно от данного Protocol.

Конкретная реализация может изменяться без влияния на потребителей.


Почему вводится отдельный Protocol

На первый взгляд может показаться, что уже существует:

AcquisitionRuntimeCommandDispatcherProtocol

Однако данный Protocol описывает инфраструктурную возможность диспетчеризации команд.

Он не определяет существование самостоятельного сервисного компонента.

Build 060.22 впервые вводит именно сервисный уровень Runtime.

Поэтому появляется отдельный сервисный контракт.

Это позволяет в будущем заменить реализацию Runtime Service без изменения Composition Root и вышестоящих компонентов.


Публичный API

Сервис предоставляет только один публичный метод.

async def dispatch(
    command: AcquisitionRuntimeCommand,
) -> None

Других публичных методов Build 060.22 не вводит.

В частности отсутствуют:

connect()

disconnect()

subscribe()

unsubscribe()

send()

Все операции выражаются исключительно через типизированные команды.


Почему отсутствуют отдельные методы

Во время проектирования рассматривалась следующая модель.

runtime.connect()

runtime.disconnect()

runtime.subscribe(...)

Она была отклонена.

Причина:

типизированные Runtime Commands уже являются официальным языком взаимодействия Runtime Layer.

Создание второго API привело бы к существованию двух независимых способов выполнения одной и той же операции.

Архитектура должна содержать единственный публичный механизм.


Зависимости Runtime Service

Сервис получает все зависимости через Dependency Injection.

Минимальный набор зависимостей выглядит следующим образом.

AcquisitionRuntimeService

        │

        ├────────► WebSocketSessionProtocol

        │

        ├────────► WebSocketTransportProtocol

        │

        ├────────► WebSocketSubscriptionManagerProtocol

        │

        └────────► AcquisitionRuntimeEventPublisherProtocol

Никакие другие зависимости Build 060.22 не предусматривает.


Почему внедряется Event Publisher

Хотя Build 060.22 ещё не реализует полноценную публикацию Runtime-событий, сервис уже принимает зависимость:

AcquisitionRuntimeEventPublisherProtocol

Это принципиальное архитектурное решение.

Причины:

  • исключается изменение конструктора в следующих Build;
  • Runtime Service сразу проектируется как источник инфраструктурных событий;
  • интеграция публикации становится локальным изменением без перестройки графа зависимостей.

На данном этапе Publisher допускается не использовать.


Почему внедряется WebSocketTransportProtocol

Большинство текущих операций выполняются через:

WebSocketSessionProtocol

Однако команды:

SendTextCommand

SendBinaryCommand

относятся к транспортному уровню.

Поэтому Runtime Service сразу получает доступ к Transport.

Это предотвращает последующее изменение конструктора.


Маршрутизация команд

Главной обязанностью Runtime Service является детерминированная маршрутизация.

Каждый тип команды имеет ровно один маршрут исполнения.


ConnectCommand

ConnectCommand

↓

WebSocketSession.start()

После успешного завершения управление возвращается вызывающему компоненту.

Сам Runtime Service не создаёт сетевое соединение.


DisconnectCommand

DisconnectCommand

↓

WebSocketSession.stop()

Сервис не закрывает транспорт напрямую.

Эта ответственность принадлежит Session.


SubscribeCommand

SubscribeCommand

↓

WebSocketSubscriptionManager.subscribe()

Runtime Service не хранит список активных подписок.

Он лишь делегирует выполнение соответствующему компоненту.


UnsubscribeCommand

UnsubscribeCommand

↓

WebSocketSubscriptionManager.unsubscribe()

После завершения операции Runtime Service не изменяет собственного состояния.


SendTextCommand

SendTextCommand

↓

WebSocketTransport.send_text()

Передаваемое сообщение считается полностью сформированным.

Runtime Service не сериализует полезную нагрузку повторно.


SendBinaryCommand

SendBinaryCommand

↓

WebSocketTransport.send_binary()

Команда делегируется транспортному уровню без каких-либо преобразований.


Официальная матрица маршрутизации

Runtime Command Исполнитель
ConnectCommand WebSocketSessionProtocol
DisconnectCommand WebSocketSessionProtocol
SubscribeCommand WebSocketSubscriptionManagerProtocol
UnsubscribeCommand WebSocketSubscriptionManagerProtocol
SendTextCommand WebSocketTransportProtocol
SendBinaryCommand WebSocketTransportProtocol

Данная таблица считается официальной спецификацией Build 060.22.

Любое изменение маршрутов требует отдельного архитектурного решения (ADR).


Детерминированность маршрутизации

Runtime Service рассматривается как детерминированный маршрутизатор.

Для каждого входящего объекта существует единственный допустимый маршрут.

Формально:

Runtime Command

↓

Dispatch Table

↓

Infrastructure Operation

Никакие дополнительные проверки, эвристики или выбор стратегии Build 060.22 не предусматривает.


Обработка неизвестной команды

Build 060.22 не допускает существование неизвестных Runtime-команд.

Если в сервис поступает объект, не входящий в объединение:

AcquisitionRuntimeCommand

это считается внутренней архитектурной ошибкой.

В таком случае сервис обязан немедленно завершить выполнение исключением.

Это гарантирует, что добавление новой команды никогда не останется незамеченным и потребует явного обновления таблицы маршрутизации.


Диаграмма взаимодействия

После реализации Build 060.22 выполнение Runtime-команд приобретает следующий вид.

Caller
    │
    │ dispatch(command)
    ▼
AcquisitionRuntimeService
    │
    ├──────────────► WebSocketSessionProtocol
    │
    ├──────────────► WebSocketTransportProtocol
    │
    ├──────────────► WebSocketSubscriptionManagerProtocol
    │
    └──────────────► AcquisitionRuntimeEventPublisherProtocol

Важно отметить, что Runtime Service остаётся полностью синхронным с точки зрения архитектуры.

Он:

  • не создаёт фоновых задач;
  • не ставит команды в очередь;
  • не выполняет повторные попытки;
  • не содержит собственного event loop.

Каждый вызов dispatch() завершается только после завершения соответствующей инфраструктурной операции.


Жизненный цикл Runtime Service

Runtime Service является долгоживущим инфраструктурным сервисом.

Типичный жизненный цикл выглядит следующим образом.

Composition Root

↓

создание зависимостей

↓

создание Runtime Service

↓

передача Runtime Service вызывающим компонентам

↓

многократные вызовы dispatch()

↓

завершение приложения

Сам Runtime Service не требует отдельной инициализации.

Также отсутствуют методы:

start()

stop()

shutdown()

dispose()

Экземпляр полностью готов к работе сразу после создания.


Отношение к состоянию

Runtime Service является stateless-компонентом.

Он не хранит:

  • состояние подключения;
  • список подписок;
  • очередь сообщений;
  • информацию о последней выполненной команде;
  • счётчики reconnect;
  • состояние Recovery;
  • состояние Consistency.

Все перечисленные данные принадлежат специализированным компонентам.

Следовательно экземпляр Runtime Service можно считать чистым координатором.


Обработка исключений

Build 060.22 сознательно не вводит собственую иерархию исключений.

Причина проста.

Runtime Service не принимает самостоятельных решений.

Он лишь вызывает инфраструктурные зависимости.

Следовательно любые исключения должны передаваться вызывающему компоненту без изменения.

Например:

Caller

↓

Runtime Service

↓

WebSocket Session

↓

ConnectionError

Исключение должно пройти обратно без обёртки.

Это сохраняет прозрачность поведения системы.


Почему исключения не преобразуются

Во время проектирования рассматривался вариант создания:

RuntimeDispatchError

Он был отклонён.

Причины:

  • потеря информации о первичном исключении;
  • необходимость лишнего уровня обработки;
  • усложнение диагностики;
  • нарушение принципа прозрачной инфраструктуры.

Runtime Service не должен скрывать происхождение ошибки.


Влияние на существующую архитектуру

Build 060.22 практически не изменяет существующую систему.

Новый сервис располагается между контрактами Runtime и инфраструктурными зависимостями.

До Build:

Runtime Commands

↓

(нет реализации)

После Build:

Runtime Commands

↓

AcquisitionRuntimeService

↓

Infrastructure

Никакие другие подсистемы не изменяются.


Влияние на Trade Stream Consistency

Подсистема:

Trade Stream Consistency

не получает никаких новых зависимостей.

Она продолжает работать исключительно с:

Trade

и

TradeStreamConsistencyProtocol

Build 060.22 не создаёт прямой связи между Runtime и Consistency.


Влияние на Trade Recovery

Trade Recovery также не изменяется.

Контроллер восстановления по-прежнему зависит только от:

TradeStreamConsistencyProtocol

Runtime Service не импортирует Recovery.

Recovery не импортирует Runtime Service.

Архитектурная независимость сохраняется полностью.


Влияние на Trades Feed

На данном этапе Trades Feed ещё не использует Runtime Service.

Интеграция будет выполнена отдельным Build:

060.23

Это позволяет протестировать Runtime Service изолированно.


План изменения структуры проекта

Build добавляет только два новых файла.

runtime/

├── acquisition_runtime_service.py

└── acquisition_runtime_service_protocol.py

Также добавляется один файл тестов.

tests/

runtime/

└── test_acquisition_runtime_service.py

Другие файлы Runtime Build 060.22 не изменяет.


Почему используется отдельный Protocol

Наличие собственного:

AcquisitionRuntimeServiceProtocol

позволяет в будущем заменить реализацию.

Например:

Simple Runtime Service

↓

Queued Runtime Service

↓

Distributed Runtime Service

Все перечисленные варианты смогут реализовывать один и тот же публичный контракт.

Поэтому вышестоящие компоненты не будут зависеть от конкретного класса.


Стратегия тестирования

Build 060.22 покрывается исключительно Unit Test.

Никакие интеграционные тесты пока не требуются.

Каждая Runtime-команда проверяется отдельно.

Минимальный набор сценариев включает:

  • соответствие AcquisitionRuntimeServiceProtocol;
  • корректную маршрутизацию ConnectCommand;
  • корректную маршрутизацию DisconnectCommand;
  • корректную маршрутизацию SubscribeCommand;
  • корректную маршрутизацию UnsubscribeCommand;
  • корректную маршрутизацию SendTextCommand;
  • корректную маршрутизацию SendBinaryCommand;
  • отсутствие побочных эффектов;
  • прозрачное распространение исключений;
  • отсутствие собственного состояния между вызовами.

Все зависимости заменяются простыми Fake-реализациями.

Использование реального WebSocket Build 060.22 запрещает.


ADR (Architecture Decision Record)

ADR-060.22-01

Решение

Создать специализированный сервис:

AcquisitionRuntimeService

реализующий выполнение всех типизированных Runtime-команд.

Статус

Accepted.


ADR-060.22-02

Решение

Ввести отдельный публичный контракт:

AcquisitionRuntimeServiceProtocol

независимо от уже существующего:

AcquisitionRuntimeCommandDispatcherProtocol

Статус

Accepted.


ADR-060.22-03

Решение

Runtime Service остаётся stateless.

Статус

Accepted.


ADR-060.22-04

Решение

Все зависимости передаются исключительно через Dependency Injection.

Статус

Accepted.


ADR-060.22-05

Решение

Не создавать новых файлов с именами:

service.py

protocol.py

test_service.py

Использовать только уникальные имена файлов.

Статус

Accepted.


Definition of Done

Build считается завершённым только при выполнении всех условий.

Обязательно должны существовать:

  • acquisition_runtime_service_protocol.py;
  • acquisition_runtime_service.py;
  • test_acquisition_runtime_service.py.

Runtime Service обязан:

  • реализовывать AcquisitionRuntimeServiceProtocol;
  • принимать зависимости через конструктор;
  • поддерживать все типы AcquisitionRuntimeCommand;
  • выполнять детерминированную маршрутизацию;
  • не хранить собственного состояния;
  • не создавать зависимости самостоятельно;
  • прозрачно распространять исключения.

Все новые Unit Test должны успешно проходить.

Build не должен изменять поведение существующих Runtime Commands, Runtime Events, Trade Recovery и Trade Stream Consistency.


Следующий Build

После завершения Build 060.22 архитектура Runtime впервые получит полноценный исполняемый сервисный слой.

Следующим этапом станет Build 060.23 — Acquisition Integration.

На этом этапе AcquisitionRuntimeService будет интегрирован в подсистему получения рыночных данных и станет использоваться как единая точка исполнения инфраструктурных Runtime-команд.

После Build 060.23 Runtime перестанет существовать только как набор контрактов и сервисов и начнёт участвовать в реальном конвейере получения данных от биржи.