Зачем: датированная спека — событие истории, а устройство компонента — живой документ; большое полотно плохо грузится и агентом, и человеком (ADR 0011). Что: вычитание #84 слито с переустройством формы: набор docs/architecture/orders/ — индекс README и семь файлов по частям устройства (нарезка по правилу «семь плюс-минус два»); датированные файлы удалены, ссылки перенацелены, AGENTS.md дополнен правилом подпапки. Приёмка владельцем #88 пройдена, черновой статус снят из README. Проверка: холодная сверка миграции свежим тредом — потерь решений нет; обход относительных ссылок набора — битых нет. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
38 lines
3.1 KiB
Markdown
38 lines
3.1 KiB
Markdown
# ADR 0010. Заказы в ODS: версии сущности вместо подмены слепка
|
||
|
||
Дата: 16 августа 2026 года. Статус: принято. Частично заменяет
|
||
[ADR 0008](0008-order-ingestion.md).
|
||
|
||
## Решение
|
||
|
||
Пакетный забор заказов остаётся прямым чтением байтового Kafka-чтеца по
|
||
команде Airflow, но порция чтения больше не считается полным слепком и не
|
||
публикуется заменой партиции `snapshot_date`. Прочитанные строки получают
|
||
`_load_id` запуска, разбираются из одного среза STG в годные строки и ошибки,
|
||
а `ods.order_snapshot` хранит принятые версии заказа в
|
||
`ReplacingMergeTree(updated_at)`. Ключ сущности — `order_id`, партиция строится
|
||
от неизменного `created_at`, все версии ключа направляются на один шард.
|
||
|
||
`snapshot_date` остаётся датой наблюдения источника, `_load_id` — координатой
|
||
запуска приёма, `_load_ts` — временем прибытия строки. Ни одна из них не
|
||
заменяет бизнес-версию `updated_at`. Физическая таблица может показывать
|
||
несколько версий; точное текущее состояние ODS открывает `ods.order_v`, которое
|
||
скрывает `FINAL` или равносильный способ выбора последней версии.
|
||
|
||
Модель заказа в DDS этим решением не задаётся. DDS получает устойчивую
|
||
типизированную поверхность ODS и отдельно решает зерно, связи и способ
|
||
материализации своей модели.
|
||
|
||
## Почему отменена подмена партиции
|
||
|
||
Прямой `SELECT` Kafka Engine заканчивается после одной полученной порции, а
|
||
протокол не несёт признака конца слепка. Поэтому `snapshot_date` не доказывает,
|
||
что в STG собрана полная партиция, и её подмена могла бы удалить уже принятые
|
||
версии прошлого дня. Маркер конца, опись или фиксация конечных офсетов сделали
|
||
бы границу настоящей, но добавили бы новый протокол без нужного стенду урока.
|
||
|
||
Малый объём позволяет оставить одно чтение на запуск как проверяемое
|
||
эксплуатационное допущение, а не границу полноты. Полный контракт разбора,
|
||
граница брака и поведение повторов заданы в
|
||
[спецификации приёма заказов](../architecture/orders/ingestion.md).
|