12 KiB
Build 060.29 — Market Data Access and Replay
Engineering Migration Report
Контроль документа
| Свойство | Значение |
|---|---|
| Build | 060.29 |
| Статус | Completed |
| Подсистема | Market Data / Historical Access and Replay |
| Компонент | Canonical History and Deterministic Replay |
| Дата завершения | 2026-08-02 |
| Версия | 1.0 |
Связанные документы
- Build 060.29 Architecture — архитектура, решения и подробные результаты подэтапов 060.29.0–060.29.8;
- Build 060.28 Engineering Migration Report — Persistent Checkpoint and Startup Recovery;
- Dzentra Target Architecture — целевая архитектура Dzentra;
- Master Roadmap — дальнейшая последовательность Build.
1. Назначение Build
Build 060.29 добавил безопасное чтение сохранённых Canonical Market Data и их детерминированное воспроизведение.
Итоговая цепочка:
PostgreSQL Canonical Market Data
↓
Historical Access
↓
bounded immutable ReplayPlan
↓
ReplaySession + Deterministic Clock
↓
явно переданный Canonical consumer
Historical Access и Replay являются read-side подсистемами. Они не заменяют Acquisition Runtime, не продвигают operational checkpoint и не записывают воспроизводимые события обратно в Market Data Storage.
2. Завершённые подэтапы
| Подэтап | Название | Статус |
|---|---|---|
| 060.29.0 | Architecture, Boundaries and Ordering Policy | Accepted |
| 060.29.1 | Historical Access and Replay Contracts | Accepted |
| 060.29.2 | Global Replay Sequence Migration and PostgreSQL Trade History | Accepted |
| 060.29.3 | Quote/Candle History and Snapshot Plan Builder | Accepted |
| 060.29.4 | Deterministic Replay Clock | Accepted |
| 060.29.5 | Replay Session and Engine | Accepted |
| 060.29.6 | Consumer and Composition Integration | Accepted |
| 060.29.7 | PostgreSQL Replay and Failure Verification | Accepted |
| 060.29.8 | Final Regression and Acceptance | Accepted |
Каждый подэтап проходил отдельный read-only review. Findings исправлялись и закрывались regression-тестами до принятия.
3. Реализованная архитектура
3.1. Глобальная последовательность Replay
Migration 9 добавила один shared PostgreSQL sequence для Trades, Quotes
и Candle revisions. Неизменяемый replay_sequence задаёт общий
детерминированный порядок для событий с одинаковым временем и
сохраняется при duplicate или provenance update.
Существующие writers совместимы с sequence для одиночных, пакетных и конкурентных записей. Default, существующие месячные и будущие partitions получают одинаковые constraints, trigger и keyset indexes.
Migration выполняется атомарно и использует единый порядок блокировок с Partition Manager и writers.
3.2. Historical Access
DB-neutral read-контракты отделены от write-only Storage API. Отдельные PostgreSQL readers возвращают типизированные неизменяемые страницы:
- Trades — по
executed_at; - Quotes — по
received_at; - Candle revisions — по
open_time.
Запросы используют полуоткрытый временной диапазон и forward keyset
pagination. Cursor связан с точным query scope. Строки PostgreSQL строго
проверяются перед созданием Canonical Trade, Quote или Candle.
3.3. Bounded Replay snapshot
Replay Plan Builder выполняет один статический snapshot-запрос в
короткой транзакции READ ONLY REPEATABLE READ. Все выбранные события
материализуются до возврата ReplayPlan; cursor, transaction и
connection освобождаются до первого вызова consumer.
Порядок Replay равен (replay_at, replay_sequence). Для Candle временем
Replay является observed_at, поэтому ревизия не появляется раньше
момента, когда она стала известна системе. Превышение max_records
завершается явной ошибкой без частичного plan.
3.4. Clock, Session и Composition
DeterministicReplayClock работает только с aware UTC-временем,
разрешает равное время и запрещает движение назад. Он не читает wall
clock и не имеет reset.
ReplaySession является необратимой one-shot сущностью. Она
последовательно продвигает Clock и ожидает один consumer-вызов для
каждого события. Ошибки и cancellation сохраняют явное terminal state и
не скрываются.
ReplaySessionFactory синхронно подготавливает новый граф
Plan → Clock → consumer → Session для каждого вызова. Default consumer,
автоматический startup, скрытая задача и отдельный ReplayEngine не
добавлены. Caller отдельно владеет session.run().
3.5. Статическая проверка типов
Pyright закреплён как обязательный gate в режиме standard, совпадающем
с Pylance проекта. Канонический запуск — scripts/check_python_types.sh;
допустимый результат — только 0 errors, 0 warnings. Тот же gate входит
в обычную offline pytest-регрессию.
4. Real PostgreSQL verification
Безопасный opt-in harness требует отдельную локальную базу с именем
dzentra_test_*, явный флаг и отдельный DSN.
Настоящий PostgreSQL 16 подтвердил:
- атомарный детерминированный backfill migration 9;
- общий sequence и совместимость всех writers/partitions;
- keyset pagination Trades, Quotes и Candle revisions;
- единый mixed-type Replay order;
- устойчивый
REPEATABLE READsnapshot при concurrent commit; - освобождение PostgreSQL resources до playback;
- limit, integrity, backend, consumer и cancellation paths;
- независимые графы двух одновременно готовящихся Replay Session;
- полный путь
Loopback Runtime → Storage → History → Replay; - отсутствие изменения durable данных и operational checkpoint.
5. Финальные результаты
Итоговая приёмка выполнена 2026-08-02:
Pyright mandatory gate: 0 errors, 0 warnings
Pyright pytest gate: 1 passed
Expanded Access/Replay/Storage unit: 545 passed
PostgreSQL Replay target repeated: 10 × 12 passed
Full PostgreSQL Storage integration: 77 passed
Full integration with PostgreSQL: 90 passed
PostgreSQL suite without opt-in: 77 skipped
Fixed stress target: 3 passed, 1 deselected
Full offline regression: 2681 passed, 95 deselected
pip check: clean
Compileall через временный pycache: clean
Tracked/untracked whitespace checks: clean
Три независимых read-only review: clean
В integration и stress наборах ResourceWarning считался ошибкой.
Production-код на финальном подэтапе 060.29.8 не изменялся: матрица не
выявила реального дефекта.
6. Эксплуатационное предупреждение migration 9
Migration 9 является блокирующей. Её длительность пропорциональна уже
накопленному объёму Market Data, потому что существующие строки получают
глобальный replay_sequence, после чего создаются constraints и
индексы.
Для текущей небольшой базы выбранный атомарный вариант разумен. Перед применением к большой production-базе обязательны резервная копия, замер длительности на сопоставимом объёме и отдельное maintenance window. Online staged migration в Build 060.29 не реализована и требует отдельного архитектурного решения.
7. Границы Build
Build 060.29 намеренно не реализует:
- initial historical backfill с биржи;
- гарантию полной биржевой истории без completeness metadata;
- точное воспроизведение порядка исходных сетевых пакетов;
- production consumers для persistent Quotes и Candles;
- автоматический запуск Replay из Bootstrap;
- default/no-op Replay consumer;
- Backtesting, Analytics API или торговую симуляцию;
- online migration 9 для большой production-базы.
Каждая Historical page отражает committed-состояние на время своего запроса. Последовательная pagination охватывает все фактически сохранённые строки диапазона только при неизменном dataset между страницами; единого межстраничного snapshot нет. Период доступной истории определяется моментом включения persistent storage и Retention Policy, а не самим Replay API.
Постороннее пользовательское изменение .gitignore не относится к
Build 060.29 и не должно включаться в его staging.
8. Итог
Build 060.29 завершён и принят.
Dzentra получила отдельный Historical Access, общий детерминированный порядок сохранённых Canonical Market Data и caller-owned Replay без скрытого lifecycle. Сохранённую рыночную историю теперь можно безопасно читать и воспроизводить одинаковыми Canonical объектами.
Следующий этап — Build 060.30, итоговый аудит и документальное закрытие ветки Trades Feed.