Airflow data interval: какой день считает ежедневный DAG
Утром 2 апреля аналитик открывает DAG run и видит logical date 1 апреля. Кажется, будто Airflow опоздал на сутки. На деле ежедневный запуск обрабатывает интервал [1 апреля 00:00, 2 апреля 00:00): раньше его окончания нельзя было считать данные за весь день. Время фактического запуска, метка запуска и диапазон данных отвечают на разные вопросы.
Airflow создаёт data interval для плановых запусков. Для расписания @daily границы обычно совпадают с полуночами в заданной временной зоне. Logical date обозначает начало интервала у такого планового запуска. Если задать SQL-фильтр по дате фактического старта задачи, повторный запуск завтра пересчитает другой день; это ломает воспроизводимость.
Границы передают прямо в запрос
SELECT COUNT(*)
FROM events
WHERE occurred_at >= '{{ data_interval_start }}'
AND occurred_at < '{{ data_interval_end }}';
Правая граница исключается намеренно: событие ровно в 00:00 2 апреля должно попасть в следующий интервал, а не в оба. Запрос показывает шаблон Airflow для строкового timestamp в ISO-формате; для столбца другого типа или другой СУБД используйте соответствующий тип параметра. В продакшене параметры лучше передавать способом, принятым у вашего оператора и драйвера, чтобы не терять тип и временную зону.
Если задача сохраняет партицию отчёта, назовите её по дате интервала, который она считает. Тогда retry того же DAG run пишет в ту же партицию, а backfill исторического run восстанавливает исторический результат. Текущее системное время полезно для аудита длительности обработки, но не должно молча подменять дату бизнес-данных.
Где logical date перестаёт быть удобным фильтром
В документации Airflow 3 для фильтрации данных рекомендуются именно data_interval_start и data_interval_end: logical date служит идентификатором run и не всегда несёт нужную бизнес-семантику. Для ручного или событийного запуска это особенно важно: нельзя предполагать, что его диапазон равен предыдущему календарному дню.
Отдельно проверьте временную зону DAG и исходного timestamp. Если данные хранятся в UTC, а бизнес-день определён по Москве, начало локального дня нужно корректно перевести в UTC. Простое прибавление 24 часов к UTC-метке не во всех часовых поясах даёт следующий локальный день из-за перехода на летнее время.
При сверке отчёта запишите три поля: интервал данных, когда запуск был запланирован и когда задача реально стартовала. Опоздание scheduler влияет на свежесть отчёта, но не должно менять состав посчитанных событий. Так можно отдельно расследовать позднюю поставку данных и поздний запуск вычисления.
Например, оператор вручную перезапустил расчёт 1 апреля вечером 5 апреля. Фильтр по now() прочитает события 5 апреля и может записать их в партицию с меткой 1 апреля. Фильтр по границам интервала возьмёт тот же набор, что и первый запуск. После этого повтор можно сравнить с прежним результатом, а расхождение объяснять изменившимися входными данными, не сдвинувшейся датой запроса.
Если источник пополняется задним числом, стабильные границы не гарантируют неизменный ответ. Опоздавшее событие с occurred_at внутри интервала попадёт в повторный расчёт. Поэтому отдельно нужны правила закрытия периода: когда его можно считать окончательным, как обнаруживать поздние записи и должен ли backfill перезаписать партицию. Это политика данных, а не свойство logical date.
При SQL-загрузке на несколько интервалов подряд полезно записать в результат обе границы и ID запуска. Тогда проверка качества может обнаружить перекрытие или дырку между соседними окнами. Например, конец интервала A должен точно совпадать с началом B. Это позволяет поймать ошибку календаря раньше, чем она проявится как скачок на графике выручки.
На курсе Data Engineering Fast‑Track вы строите DAG для загрузки и backfill конвейера. Посмотрите программу, чтобы связать календарный интервал с проверкой результата в lakehouse.
Если исторический интервал запускают снова, прочитайте также разбор дублей при backfill.
Продолжить на практике
- Data Engineering Fast‑Track: Kafka → Airflow → Spark ↗
Практический fast-track по data engineering: за 4–6 недель собираем рабочий конвейер Kafka → Spark → Lakehouse под управлением Airflow. Разберём batch и streaming, окна и watermark, схемы и контракты. Мини‑проекты, Docker Compose, шаблоны DAG и пайплайнов. Курс подойдёт инженерам, аналитикам и тем, кто хочет освоить современные пайплайны данных с уверенным Python.
