Files
clickstream-data-platform/docs/architecture/dds
ddadminandClaude Opus 5 176cf5520d feat(dds): добавлена модель сессии и нарезка визитов окнами
Зачем:
- Дать слою расчётную сущность, которой в потоке нет: стенд режет визиты сам,
  а VisitID генератора остаётся эталоном самопроверки.
- Отделить прожитый день от живого — иначе визит, начатый в 23:50, замёрз бы
  обрезанным навсегда: пересобирать замёрзший день слой не станет.

Что:
- Добавлены dds.session_rep/_dist, двойник-донор dds.session_stage_rep/_dist и
  публичный договор dds.session_v.
- Нарезка стоит на двух окнах: первое ставит шов там, где пауза длиннее
  тридцати минут, второе считает нарастающий итог швов — номер визита. Границу
  суток держит разбиение окна, отдельной проверки ей не нужно.
- Порядок в окнах полный, по метке времени и event_id: сортировок две, и при
  равных метках они разошлись бы, разорвав сессию надвое.
- Объём прогона считается от первой дыры в слое по последний прожитый день;
  прожитый день выводится из позиции мира и первого дня событий. Собирать
  нечего — группа задач пропускается, а не зеленеет впустую.
- В dds_transform появилась группа session рядом с заказом; зависимости по
  данным между ними нет.
- Потолок max_active_tasks: размноженная замена без него выносит планировщика
  за отведённые ему 640 МиБ.
- parallel_distributed_insert_select у сессий не назначается вслух — ключ
  шардирования у источника и цели один по контракту ко-локации.
- Записано, что позиция отвечает за «прожит», а не за «доехал»: сторож хвоста
  потока приезжает отдельным тикетом.

Проверка:
- make lint
- make smoke (21 проверка), make check-clickhouse (10), make check-services
- Стартовый мир, пересобранный с нуля: 79367 сессий за восемь дней;
  расхождение с uniqExact(VisitID) по паре «кука × день» — ноль; все 401185
  событий ровно в одной сессии; session_id уникальны.
- Ни одной паузы длиннее тридцати минут внутри сессии и ни одной пары соседних
  визитов куки, разделённой меньшим промежутком.
- Повтор после DROP PARTITION ALL: те же session_id и то же содержимое строк.
- Снесённая руками партиция 2026-06-04: следующий прогон взял хвост от неё,
  дни до дыры не тронуты.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-26 07:56:44 -04:00
..

Слой DDS: бизнес-модель хранилища

Устройство детального слоя: сущности, которыми хранилище говорит с витринами, их связи и правила слоя. Набор собирается развилками карты #127 (этап 4) и правится по мере постройки.

Рамки заданы мастер-спекой «Боевой реализм стенда (v2)»: карта таблиц и витрины — раздел 7, сверка — раздел 4, склейка идентичностей — раздел 5. Дом выбран развилкой #130 — первой, которой понадобилось записать резолюцию в доки: записи этапа 4 живут здесь, по хранилищную сторону границы «источник | хранилище». Устройство источников остаётся их собственным наборам (заказы бэкенда) — генератор переносим и о нашем DDS не знает.

Карта модели

Целостность модели — связи и ко-локация — живёт в этом разделе; файлы сущностей держат глубину и на карту ссылаются.

  • Заказ (dds.order_v, хранение dds.order_rep / _dist) — физическая сущность: одна строка — заказ в текущем состоянии, позиции массивами в строке, наполняется заменой партиций — модель заказа.
  • Сессия (dds.session_v, хранение dds.session_rep / _dist) — расчётная сущность: одна строка — визит, нарезку по правилу визита стенд делает сам, VisitID генератора — эталон сверки; наполнение заменой дневной партиции — модель сессии.
  • Событие (dds.event_v) — контракт над ODS, а не копия: представление, переводящее событие на язык бизнес-модели, — контракт события.
  • Карта идентичностей (dds.identity_map_v, хранение dds.identity_map_rep / _dist) — кука ↔ пользователь магазина — модель карты.

Связи держатся двумя ключами моста (спека, разделы 4 и 5): purchaseID[1] события равен order_id заказа — по нему идут сверка и сборка склейки; user_id заказа связывает куки одного человека. Ко-локацию задаёт шардирование: события и карта идентичностей раскладываются одним выражением от куки, заказы — от order_id. Поэтому обогащение витрин склейкой локально, а сверка и сборка карты ходят через GLOBAL JOIN с обеими сторонами-подзапросами (исследование соединений).

Правила слоя

  • DDS обслуживает человека с дашбордом: время лежит в поясе счётчика, пересчёт — один раз при наполнении слоя (дока хранилища, «Часовые пояса»).
  • Публичный договор каждой сущности — _v; роли объектов и конвенция чтения заданы докой хранилища, «Имена объектов».
  • Служебные колонки — координаты собственной загрузки слоя; чужие ярлыки не переносятся, а спрашиваются у их слоя по ключу сущности. Вывод правила и цепочка расследования — модель заказа.
  • Наполняет слой дневной конвейер: запуск, объём прогона и замена партиций на кластере — его устройство.

Родословная

Дом набора и первая сущность собраны развилкой #130 карты #127; форма набора — ADR 0011.