From b9f570fc40831fff6d1fc0f1c633da92529c1a14 Mon Sep 17 00:00:00 2001 From: Dmitry Dementiev Date: Sun, 16 Aug 2026 23:06:14 +0300 Subject: [PATCH] =?UTF-8?q?docs(orders):=20=D0=B7=D0=B0=D0=BA=D1=80=D1=8B?= =?UTF-8?q?=D1=82=D1=8B=20=D0=BD=D0=B0=D1=85=D0=BE=D0=B4=D0=BA=D0=B8=20?= =?UTF-8?q?=D1=85=D0=BE=D0=BB=D0=BE=D0=B4=D0=BD=D0=BE=D0=B3=D0=BE=20=D1=80?= =?UTF-8?q?=D0=B5=D0=B2=D1=8C=D1=8E=20=D0=B4=D0=B5=D1=84=D0=B5=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Зачем: холодная сверка сборки с резолюциями нашла два завышенных обещания, недовнесённую правку и битую ссылку (DEF-1, DEF-2, DEF-3, DEF-5); DEF-4 отложен до триажа вычитания #84. Что: обещание «переливает ровно тот слепок» смягчено до штатного прогона с хвостом после падения (спека §9 и ADR 0008); довод против сдвига created_at перестроен на канон аудита источника (§4); в §7 мастер-спеки довнесено чтение amount_delta через сравнение позиций (#72); ссылка в §1 ведёт на раздел 8. Проверка: узкая перепроверка тем же ревьюером. Co-Authored-By: Claude Fable 5 --- docs/adr/0008-order-ingestion.md | 7 ++++--- docs/specs/2026-07-30-stand-v2-realism.md | 5 +++-- docs/specs/2026-08-16-orders.md | 16 ++++++++++------ 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/docs/adr/0008-order-ingestion.md b/docs/adr/0008-order-ingestion.md index 50ea9b7..20c1fce 100644 --- a/docs/adr/0008-order-ingestion.md +++ b/docs/adr/0008-order-ingestion.md @@ -18,9 +18,10 @@ заменяет партицию дня в `ods.order_snapshot`. Тот же даг проигрывает модельный день генератором, поэтому переливается ровно то, что он положил в топик. Уточнение со сдвигом отправки, решённым позже (#71, [спека -заказов](../specs/2026-08-16-orders.md), раздел 2): даг, играющий день D, -кладёт и забирает слепок дня D−1 — по-прежнему ровно то, что сам положил, но -это слепок предыдущего дня, а не сыгранного. +заказов](../specs/2026-08-16-orders.md), раздел 2): даг, играющий день D, в +штатном прогоне кладёт и забирает слепок дня D−1 — слепок предыдущего дня, а +не сыгранного. После падения между шагами в топике может ждать и хвост +прежних слепков; забор принимает всё приехавшее. Прямое чтение из Kafka-движка требует двух настроек, и вторая не очевидна: `stream_like_engine_allow_direct_select = 1` разрешает читать чтеца запросом, diff --git a/docs/specs/2026-07-30-stand-v2-realism.md b/docs/specs/2026-07-30-stand-v2-realism.md index 411a6de..f23b854 100644 --- a/docs/specs/2026-07-30-stand-v2-realism.md +++ b/docs/specs/2026-07-30-stand-v2-realism.md @@ -465,8 +465,9 @@ Kafka день переигрывается генератором заново: `total`: промокод и доставка клиенту не видны), `status`, `mismatch_class` (`match` / `cancelled` / `lost_event` / `duplicate_event` / `amount_delta`, в порядке приоритета — классы пересекаются, побеждает более ранний). - `match` — большинство строк; `amount_delta` — только необъяснённый остаток - после приведения к сравнимой базе; его создаёт генератор намеренно + `match` — большинство строк; `amount_delta` — остаток, не объяснённый + приведением к сравнимой базе: сравнением позиций он объясняется, и на этом + стоит урок класса C; создаёт его генератор намеренно (~1–2% заказов, см. раздел 4). Строка «`purchase` без заказа» внутри живого окна — опоздание, ждущее слепка, а не расхождение: она получает служебный класс `awaiting_order` diff --git a/docs/specs/2026-08-16-orders.md b/docs/specs/2026-08-16-orders.md index 3270735..644124a 100644 --- a/docs/specs/2026-08-16-orders.md +++ b/docs/specs/2026-08-16-orders.md @@ -79,7 +79,7 @@ В модели строка заказа в базе источника создаётся синхронно с покупкой, поэтому день рождения заказа и день создания строки совпадают. Смысл полей от этого не меняется: `created_at` и `updated_at` — аудит строки по часам базы источника, -бизнес-время покупки живёт в `purchase.UTCEventTime` (раздел 6). +бизнес-время покупки живёт в `purchase.UTCEventTime` (раздел 8). Отклонено: *выводить заказ разбором собственного вывода* (`purchaseID`, сырой `ecommerce`) — бэкенд стал бы читателем трекера ровно там, где стенд учит, что @@ -264,9 +264,11 @@ d…d+δ−1 её нет, а с d+δ она появляется в том со перестало бы быть верным; при δ ≤ 2 у всякого заказа слепков не меньше пяти. Легенда: заказ ушёл в ручную обработку и попал в выгрузку позже. Следствие для переливки не ново: у прошлых дней окна меняется и состав, а не только суммы — -«дыхание» статусов это уже требовало. Отклонено: *сдвиг `created_at`* — заказ -уехал бы в чужую партицию, и «выручка дня D» перестала бы отвечать покупкам -дня D — сломалась бы та самая сверка, ради которой всё строится. +«дыхание» статусов это уже требовало. Отклонено: *сдвиг `created_at`* — +подделка аудита источника: день создания строки разошёлся бы с днём покупки, +чьё равенство держит синхронная модель (раздел 1), заказ уехал бы в чужую +партицию, и «выручка дня D» перестала бы отвечать покупкам дня D — сломалась +бы та самая сверка, ради которой всё строится. **Пересечения.** Броски независимы, пересечения выходят арифметикой, приоритет мастер-спеки работает по-настоящему. Исключений два, и оба названы выше: дубль @@ -473,8 +475,10 @@ Kafka не задаёт границы полного слепка, поэтом Стенд получает два режима приёма рядом — поток против слепка, push против pull, — и это опорная точка раздела 12 мастер-спеки. Тот же даг проигрывает -модельный день и забирает слепок; со сдвигом отправки он переливает слепок -предыдущего дня — ровно тот, который сам и положил в топик. +модельный день и забирает слепок; в штатном прогоне это слепок предыдущего +дня, который он сам и положил в топик. После падения между отправкой и +забором в топике может ждать и хвост прежних слепков — забор принимает всё +приехавшее, версии в ODS это поглощают (спека приёма). ## 10. Правила кода этапа 3