Files
ddadminandClaude Fable 5 2e42cf63ff chore(scratch): сохранены слепок трекера и handoff миграции на Gitea
- Зачем:
  - GitHub-аккаунт заблокирован 2026-07-26; трекер карты «боевой
    реализм» перенесён на git.dementev.space, контекст нужен новой
    сессии независимо от исхода апелляции.
- Что:
  - .scratch/backup/ — слепок всех 27 issues и резолюция тикета #15
    на момент блокировки;
  - .scratch/handoffs/ — handoff с состоянием карты, нюансами доступа
    к Gitea и списком хвостов (апелляция, выбор основного трекера).
- Проверка:
  - тексты читаются; ссылки на Gitea-трекер открываются
    (git.dementev.space/ddmitry/clickstream-ch-kafka-superset-demo).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 22:03:00 +03:00

8.1 KiB
Raw Permalink Blame History

Ответ

Сумма заказа живёт на обеих сторонах, и стороны законно расходятся: клиентское событие несёт объявленную сумму (то, что сайт продиктовал трекеру через dataLayer — до пересчёта на бэкенде), заказ бэкенда — итоговую правду со статусами. Правило стенда: поведение и атрибуцию считаем по трекеру, деньги — по бэкенду. Правило выучивается на конфликте: суммы у менти не сойдутся, и он сам раскопает почему.

Клиентская сторона (широкое событие, рамка #18)

  • Таксономия торговых событий: pageview + add_to_cart + purchase. Полный словарь Метрики (detail, remove, impressions) не берём: механика та же, объём массивов большой, новых идей нет — остаётся теорией в документе о реализме.
  • purchase несёт purchaseID/Revenue/Currency/Coupon + массивы product* состава заказа + сырую строку ecommerce (по образцу выгрузки Метрики, фактура — #27).
  • add_to_cart — массивы product* с одним товаром. Оживают мёртвые счётчики purchases/add_to_carts в v_utm_effectiveness без правки витрины.

Сторона бэкенда (второй источник, рамка #18)

  • Формат выгрузки: полный ежедневный слепок заказов в пределах окна изменяемости K дней. Запись = снапшот заказа: order_id, user_id, времена, status (created/paid/cancelled), updated_at, итоговые суммы (товары / скидка / доставка / итого) + позиции вложенным JSON (items: [{sku, qty, price}]) — «родной» экспорт бэкенда, а не диалект Метрики.
  • Обоснование слепка (а не инкремента): очень частый боевой формат; идемпотентный приём и самовосстановление (пропущенный день ничего не ломает); дедуп до последней версии становится обязательным с первого дня. Окно K делает объём защитимым (за окном заказ неизменяем — возить незачем) и даёт границу пересчёта: выручка дня D «дышит» K дней, потом замерзает.
  • Приём: дедуп через ReplacingMergeTree/argMax; разбор JSON-позиций — один раз в трансформации ODS → DDS, дальше витрины работают с плоскими массивами. Это единственный носитель навыка «вложенный JSON в ClickHouse» в стенде.
  • В docs/generator-realism.md — честный абзац trade-off «инкремент экономнее, слепок надёжнее» и сноска про compacted topic как родной Kafka-паттерн для состояния сущности.

Сверка

  • Ключ: клиентский purchaseID = order_id бэкенда (магазин знает номер заказа на /confirmation — как actionField.id у Метрики).
  • Конструируемые расхождения — перечислимый список из четырёх причин, детерминированных от seed:
    • A. Отменаpurchase есть, заказ дошёл до status='cancelled' (бесплатно из статусов);
    • B. Потерянное событие — заказ есть, purchase не доехал (вероятность в генераторе);
    • C. Дельта суммы — систематическая, по построению: клиент объявляет сумму товаров до промокода и доставки, бэкенд — итог; менти может вывести формулу связи;
    • D. Дубль события — повторный purchase от обновления /confirmation (вероятность).
  • Пятый эффект бесплатно даёт формат доставки: опоздание (заказ впервые появляется в слепке D+1/D+2) — «вчера не сходилось, сегодня сошлось».
  • Не берём: сироту-фрод (дублирует B механически) и расхождение часов клиент/сервер — это жители тумана «Грязь в данных», придут своим тикетом.

Слои и витрины

  • DDS: одна новая сущность dds.order (последняя версия заказа, позиции разобраны в массивы). purchase отдельной сущности не получает — это строка широкого события.
  • DM, три роли: выручка (v_revenue_daily, по категориям через dictGet каталога) — строится только от заказов; сверка (v_purchase_vs_orders) — FULL OUTER JOIN по ключу с классификатором расхождения; атрибуция (v_utm_effectiveness) — остаётся клиентской, плюс объявленная выручка по UTM. Точный состав колонок — в спеку (#17).

Эталонный мир

Пересборка артефакта неизбежна и уже оплачена решением #18; этот тикет нагружает её смыслом: манифест расширяется контрольными числами заказной стороны — заказы и выручка по дням, и ровно N потерянных / M дублей / K отмен для самопроверки лабы сверки. Политика версионирования артефакта здесь не решается (пункт тумана карты).

Ограничения исполнения и страховочные срезы

Аудитория — джун после базовой программы: расхождения — перечислимый список, не хаос. Если при сборке спеки (#17) суммарный объём испугает, резать в порядке: (1) статусы сузить до created/cancelled — урок дедупа держится на самом слепке; (2) расхождения вводить поэтапно — сначала A+C, потом B+D; (3) окно K сделать константой мира, а не параметром.

Отклонено по дороге

Событийный лог заказов (сборка автомата — дальше от типовой работы DE), CDC-формат (имитация Debezium без Debezium), шапка+строки (воскрешает склейку по ключам), отдельный поток возвратов, полный словарь торговых событий Метрики, механика Sign/CollapsingMergeTree (остаётся кандидатом на потом, её дом — клиентская сторона, поток визитов Метрики Про, не заказы).

Фактура: docs/research/2026-07-26-yandex-clickstream-format.md (#27), резолюция «Модель данных» (#18).