Files
dzentra_bot/docs/migrations/build_060_27.md

10 KiB
Raw Permalink Blame History

Build 060.27 — Persistent Market Data Storage

Engineering Migration Report


Контроль документа

Свойство Значение
Build 060.27
Статус Completed
Подсистема Market Data Acquisition / Persistent Storage
Компонент Canonical Market Data Storage
Дата завершения 2026-08-01
Версия 1.0

Связанные документы


1. Назначение Build

Build 060.27 добавил долговременное PostgreSQL-хранилище Canonical Market Data. Production Trade Stream теперь может сохранять Trades независимо от времени жизни процесса, а Quotes и Candles получили готовые storage-контракты и repositories без подключения существующих consumers.

Главная гарантия интеграции:

validated Canonical Trade
        ↓
durable PostgreSQL write
        ↓
operational checkpoint advancement

Ошибка включённого persistent storage является фатальной. Runtime не продвигает checkpoint и не продолжает работу так, будто Trade сохранён.


2. Завершённые подэтапы

Подэтап Название Статус
060.27.0 Storage Contract and Boundaries Accepted
060.27.1 PostgreSQL Schema, Migrations and Pool Accepted
060.27.2 Persistent Trade Repository Accepted
060.27.3 Quote and Candle Repositories Accepted
060.27.4 Storage API and Retention Accepted
060.27.5 Trade Runtime Persistence Integration Accepted
060.27.6 Bootstrap and Lifecycle Integration Accepted
060.27.7 Integration and Failure Verification Accepted
060.27.8 Final Regression and Acceptance Accepted

Каждый подэтап проходил отдельный read-only review. Findings исправлялись и закрывались regression-тестами до принятия.


3. Реализованная архитектура

3.1. Schema, migrations и pool

Создана PostgreSQL schema market_data с partitioned таблицами:

  • trades — Canonical Trades;
  • quotes — неизменяемые Canonical Quote snapshots;
  • candle_revisions — наблюдавшиеся ревизии Candles;
  • partition_registry — реестр Dzentra-managed partitions.

Семь упорядоченных миграций применяются в одной транзакции под transaction-level advisory lock. История хранится в public.storage_schema_migrations; неизвестная версия или другое имя миграции являются фатальным schema mismatch.

PostgresConnectionPool не выполняет I/O в конструкторе. Pool явно открывается Application lifecycle перед Runtime и закрывается только после полной остановки Trade Runtime.

3.2. Canonical repositories

Repository-контракты различают три результата:

  • INSERTED — сохранено новое событие;
  • DUPLICATE — идентичное событие уже существует;
  • PROVENANCE_UPDATED — Canonical payload совпал, добавлен новый путь наблюдения.

Trade identity задаётся venue + symbol + trade_id + executed_at. Время защищает историю от коллизии после полного signed 32-bit rollover Trade ID. Разный transport source не создаёт Canonical conflict, а различие цены, количества, времени или стороны создаёт явную ошибку.

Quote identity использует venue + symbol + received_at. Candle identity использует venue + symbol + interval + open_time + observed_at, поэтому промежуточные и финальные ревизии не перезаписываются скрытно.

Одиночные и пакетные операции транзакционны. Конфликт или database error откатывает всю пакетную запись.

3.3. Partitions и retention

Каждая основная таблица имеет default partition. Управляемый partition manager под общим advisory lock:

  1. проверяет фактическое состояние PostgreSQL и registry;
  2. создаёт месячную таблицу;
  3. переносит подходящие default rows;
  4. подключает partition в той же транзакции.

Retention по умолчанию выключен. Явный запуск удаляет только зарегистрированные истёкшие partitions и строки раньше точного UTC cutoff. Очистка всех выбранных типов выполняется атомарно.

3.4. Runtime и Bootstrap

Live и Recovery используют один TradeObservationSinkProtocol через общий TradeStreamConsistencyController. Единственный владелец записи обеспечивает одинаковую последовательность для обоих путей данных.

Синхронная PostgreSQL-запись выполняется вне asyncio event loop через принадлежащую Runtime задачу. Cancellation ожидает уже начатую запись и не оставляет фонового worker.

Storage включается только явным MARKET_DATA_STORAGE_ENABLED=true и требует включённый Trade Stream. При выключенном флаге зависимости не строятся, pool не открывается, migrations не запускаются.


4. Real PostgreSQL verification

Безопасный opt-in harness требует одновременно:

  • DZENTRA_RUN_POSTGRES_TESTS=1;
  • отдельный DZENTRA_TEST_POSTGRES_DSN;
  • явный localhost, loopback address или local socket;
  • имя базы с префиксом dzentra_test_.

PostgreSQL service, неявный endpoint и смешанный local/remote fallback запрещены. Перед destructive cleanup harness повторно проверяет точное имя фактической базы и специальное имя контрольного соединения.

Настоящий PostgreSQL подтвердил:

  • атомарность migrations и repositories;
  • участие обеих concurrent migration/partition caller-сессий;
  • insert, duplicate, provenance и conflict paths;
  • перенос default rows и точность retention cutoff;
  • Runtime persistence через Live и reconnect/recovery;
  • fatal propagation database failure;
  • правильное закрытие pool и отсутствие оставшихся соединений.

5. Финальные результаты

Итоговая приёмка выполнена 2026-08-01:

Targeted Storage/Runtime unit suite:       307 passed
PostgreSQL control run:                     15 passed
PostgreSQL repeated ten times:             150 passed
Combined integration suite:                 26 passed
Fixed stress target:                         3 passed, 1 deselected
PostgreSQL suite without opt-in:            15 skipped
Full offline regression:                  2119 passed, 31 deselected
git diff --check:                           clean
Untracked files diff check:                 clean

В integration и stress наборах ResourceWarning считался ошибкой. Одноразовый PostgreSQL 16 работал на tmpfs и после приёмки был остановлен и удалён. Итоговый read-only review не обнаружил открытых findings.


6. Границы Build

Build 060.27 намеренно не реализует:

  • persistent Runtime checkpoint;
  • Startup Recovery после перезапуска процесса;
  • Historical Queries и Data Access Layer;
  • Replay API и Analytics API;
  • автоматический partition/retention scheduler;
  • подключение существующих Quote/Candle consumers;
  • хранение raw exchange documents.

Persistent Checkpoint и Startup Recovery относятся к Build 060.28. Historical Access и Replay относятся к Build 060.29. Полная итоговая ревизия документации подсистемы остаётся задачей Build 060.30.

Постороннее пользовательское изменение .gitignore не относится к Build 060.27 и не должно включаться в его staging.


7. Итог

Build 060.27 завершён и принят.

Dzentra получила транзакционное долговременное хранилище Canonical Market Data и production persistence для Trades. Operational checkpoint теперь продвигается только после подтверждённой durable-записи, а ошибка Storage завершает Runtime без скрытой потери истории.

Следующий этап — Build 060.28, Persistent Checkpoint and Startup Recovery.