Зачем: - Один запуск должен одинаково работать из жизненного цикла, вручную после разгона и повторно после отказа. Что: - Добавлена последовательная сцепка DDS и DM с ожиданием каждого слоя. - DDS дожидается смещений Kafka и очереди доставки ClickHouse за общий срок. - ETL встроен в создание мира и живой день; документация приведена к новому графу. Проверка: - make config-test; make lint. - make smoke: 21/21; make check-clickhouse: 10/10; make check-services: 7/7. - make rebuild-storage, живой и пакетный дни, искусственный отказ и ручное восстановление ETL.
51 lines
4.1 KiB
SQL
51 lines
4.1 KiB
SQL
-- DDS: объём пересборки сессий — какие дни собирает этот запуск.
|
||
--
|
||
-- Ответ — две даты, границы непрерывного отрезка; список дней между ними
|
||
-- разворачивает даг. Пустой ответ означает пустой источник. Пустой первый
|
||
-- день — что собирать нечего: все прожитые дни уже в слое, и прогон честно
|
||
-- пропускает сборку.
|
||
--
|
||
-- Файл кончается без точки с запятой: почему — sql/dds/order_scope.sql.
|
||
--
|
||
-- Правый край — последний прожитый день, и знает его только позиция мира.
|
||
-- События живой день от прожитого не отличают: и посреди дня D, и сразу после
|
||
-- его конца max(EventDate) = D. А разница несущая — визит, начатый в 23:50,
|
||
-- посреди дня ещё идёт, и собранная сессия оказалась бы обрезанной навсегда:
|
||
-- пересобирать замёрзший день слой не станет
|
||
-- (docs/architecture/dds/session.md, «Движок и наполнение»).
|
||
--
|
||
-- Позиция — номер первого несыгранного дня, счётчик прожитого. Своей копии
|
||
-- начала оси стенд из-за неё не заводит: начало он спрашивает у данных, и
|
||
-- дата дня N в них — константа, начало оси плюс N. Держится якорь на том, что
|
||
-- ранние дни из ods.event не исчезают: срок жизни назначен сырью и таблицам
|
||
-- ошибок, самому событию — нет (sql/ddl/20-ods-tables.sql).
|
||
--
|
||
-- За «доехал» позиция не отвечает — только за «прожит». Перед расчётом объёма
|
||
-- первый шаг дага дожидается хвоста потока и очереди доставки: иначе
|
||
-- недожеванный хвост заморозил бы недособранный день
|
||
-- (docs/architecture/etl.md, «Готовность источника»).
|
||
WITH
|
||
(SELECT min(EventDate) FROM ods.event_dist) AS first_source_day,
|
||
first_source_day + ({position:UInt16} - 1) AS last_lived_day,
|
||
-- Хвост считается от первой дыры, а не от последнего собранного дня:
|
||
-- замены партиций падают порознь, и счёт по максимуму собранного дня
|
||
-- дыру позади себя не заметил бы (доводы целиком — sql/dds/order_scope.sql).
|
||
-- У сессий это единственный способ дыру найти: дышащего окна, которое
|
||
-- пересобрало бы день заодно, здесь нет.
|
||
--
|
||
-- GLOBAL обязателен: обе таблицы распределённые, и обычный NOT IN сверял
|
||
-- бы дни источника с локальной частью слоя на каждом шарде.
|
||
-- minOrNull отличает «дыр нет» от даты по умолчанию.
|
||
(
|
||
SELECT minOrNull(day)
|
||
FROM (SELECT DISTINCT EventDate AS day FROM ods.event_dist)
|
||
WHERE day GLOBAL NOT IN (SELECT session_date FROM dds.session_dist)
|
||
) AS first_missing_day
|
||
SELECT
|
||
-- Живой день в слое отсутствует всегда, и работой это не считается:
|
||
-- дырой он станет, только когда мир его проживёт.
|
||
if(first_missing_day <= last_lived_day, first_missing_day, NULL) AS first_day,
|
||
last_lived_day AS last_day
|
||
-- FINAL не нужен: повтор доставки не двигает ни край оси, ни набор дней.
|
||
WHERE (SELECT count() FROM ods.event_dist) > 0
|