Files
airflow-manual/docs/specs/2026-09-28-practice-improvement-plan.md

37 KiB
Raw Permalink Blame History

План обновления практики по Airflow

Дата: 2026-09-28. Подход согласован с автором курса. Реализация завершена. Результаты и границы проверки сохранены в протоколе.

Этот документ сохраняет решения, порядок доработки и результаты проверки. Текущие задания находятся в educational-tasks.md, запуск стенда описан в README.

Цель и границы

Стенд знакомит студентов с Apache Airflow и входит в программу Data Engineering. Перед ним студенты проходят Python, pandas, SQL и Docker. Самостоятельное построение цельных процессов обработки данных относится к последующим курсовым работам.

Результат этого блока: студент умеет запустить готовый DAG, найти его граф и логи, внести небольшое изменение по образцу и объяснить наблюдаемое поведение. Практика остается набором небольших экспериментов с инструментом.

Обновление сохраняет ознакомительный формат и версию Airflow 2.9.x. Основной маршрут выполняется на существующем стенде; внешние интеграции относятся к заданиям по желанию. Учебная имитация отдельных операций допустима, если описание и логи честно называют ее имитацией.

Порядок работы

Перед продолжением сверить чек-лист с текущими файлами и историей Git. Прочитать согласованные решения ниже, затем выполнить первый незавершенный этап. Локальные решения в этих границах принимать и записывать в рабочей таблице; противоречия с согласованной целью выносить на обсуждение.

  • Зафиксировать подход и находки в этом документе; добавить ссылки из README стенда и AGENTS.md.
  • 1. Разобрать все исходные задания. Создать здесь рабочую таблицу с колонками: исходное задание (DAG/раздел и номер), изучаемая возможность, исходное состояние и зависимости, решение с обоснованием, место в будущем маршруте, наблюдаемый результат. Решения: оставить основным, разделить, перенести в дополнительные или переформулировать. Исходный набор - 25 заданий в educational-tasks.md на коммите 13e3102; после переработки число упражнений может измениться. Готово: учтены 25 из 25 исходных заданий, у каждой части разделенного задания определена обязательность, а все зависимости основного маршрута обеспечены без выполнения дополнительных упражнений. Сопоставление с главами учебника объясняет выбор тем; новые темы добавляются только при выявленной необходимости для цели блока.
  • 2. Проверить и исправить несогласованности. Сверить каждую строку раздела "Найденные несогласованности и препятствия" с актуальным кодом. Для каждой записать итог: исправлено, не подтвердилось с объяснением или оставлено как явно описанный учебный сценарий. Готово: все находки разобраны; подтвержденные ошибки устранены, измененное поведение проверено на версии стенда. Невыполненная проверка остается открытой.
  • 3. Переработать показательный блок обработки ошибок. Подготовить основной управляемый эксперимент с повтором, наблюдаемые результаты и отдельное усложнение по желанию. Готово: исходное состояние и возврат к нему описаны; воспроизведены успех после повтора и окончательная ошибка; логи, состояния задач и итог DAG Run совпадают с описанием. Этот блок служит образцом объема и оформления остальных упражнений.
  • 4. Переработать остальные блоки. Применить выбранное распределение и образец к остальным заданиям. Готово: каждая строка рабочей таблицы ссылается на итоговое упражнение или содержит причину объединения; у каждого упражнения есть обязательность и проверяемый результат; подготовка и восстановление общих данных описаны там, где нужны.
  • 5. Согласовать навигацию. Обновить маршрут и оценку прогресса в educational-tasks.md, корневом README и README стенда. Сверить dag-specifications.md с итоговым содержанием. Готово: ссылки ведут к актуальным упражнениям; документы согласованно описывают порядок и условия завершения; устаревшие прототипы и необоснованные оценки времени удалены или исправлены.
  • 6. Пройти маршрут двумя способами. Выполнить только основную практику, затем дополнительные упражнения с переходами обратно к основной. Готово: обе последовательности пройдены в изолированном окружении; указанные результаты подтверждены в данных и UI; сохранены условия запусков, результаты и ограничения по правилам раздела "Как проверять результат доработки".

По мере выполнения обновлять рабочую таблицу и чек-лист. У закрытого этапа указывать ссылку на коммит или запись о проверке. Если часть проверок недоступна, записать причину и продолжать независимую работу; соответствующий этап остается незавершенным.

Текущее состояние реализации

Исправления DAG сохранены в cf1b770, задания и навигация в d8dfe83, уточнения после прохождения в 1277bff. В f6b450c задания перенесены в корень репозитория.

Все 25 исходных заданий сопоставлены с 34 упражнениями: 16 основных и 18 по желанию. Основной маршрут пройден без дополнительных упражнений. Затем проверены дополнительные расширения и возвраты к базовой схеме, режимам и настройкам. Сохранены условия и результаты проверки, состояния 70 контрольных и диагностических запусков и снимки UI.

Открытых этапов реализации нет. При следующей правке сверять затронутые задания с кодом и протоколом. Проверка не измеряет трудность на студентах; SMTP проверен локальным приемником, без внешнего почтового провайдера.

После независимого педагогического ревью исправлены примеры в главах 2, 7 и 9 и уточнены ссылки на теорию перед практикой. Значимость находок, принятые решения и исполнение примеров записаны в перепроверке ревью. Предложение расширить основную практику опытом с Clear оставлено до проверки на студентах; состав упражнений сохранен.

Согласованные решения

  1. Последовательность внутри блока. Студент запускает исходный пример, меняет одну существенную настройку или часть графа и наблюдает результат. Изменения основных заданий внутри блока сохраняются.
  2. Ясное начало каждого блока. Указаны исходный DAG, необходимые файлы, таблицы и настройки, а также изменения, которые остаются от предыдущей работы. Блок определяется учебным смыслом: загрузка CSV и последующая DQ-проверка могут объединять два DAG.
  3. Основная практика и задания по желанию. Обязательность отделена от сложности. Дополнительные задания расположены в конце своего блока; их результаты не нужны для продолжения основной практики. Пропуск дополнительного задания не препятствует завершению блока.
  4. Разделение смешанных заданий. Если одно упражнение объединяет знакомство с возможностью Airflow и значительное усложнение, оно разделяется. Например, TaskGroup и настройка настоящей отправки писем не должны быть одним обязательным заданием.
  5. Наблюдаемый результат. У каждого задания есть раздел "Что должно получиться": конкретное поведение в UI, сообщение в логах или результат в файле/таблице. Преднамеренная ошибка может быть правильным результатом упражнения.
  6. Управляемые учебные сценарии. Основные примеры ветвления и повторных попыток позволяют гарантированно увидеть нужный случай. Случайность допустима в данных, если она не мешает наблюдать изучаемое поведение и проверять результат.
  7. Понятное завершение. Основная практика дает достаточное знакомство для перехода дальше по программе. Выполнение всех дополнительных упражнений не является скрытым условием прохождения курса.

Дополнительное задание, меняющее общую таблицу или настройку, должно описывать возврат к состоянию, необходимому следующему блоку. Перенос задания в конец раздела сам по себе эту проблему не решает. Восстановление касается только объектов упражнения, без общего сброса стенда или чужих изменений.

Как оформлять задания

Задания находятся в корне репозитория рядом с главами учебника: educational-tasks.md. В airflow-docker/ остаются инструкция запуска, стенд и примеры DAG. Основные и дополнительные упражнения сохраняются в одном документе.

В начале блока: связь с главами учебника, необходимые исходные условия и короткий запуск готового примера. У задания:

  • пометка "Основная практика" или "По желанию"; сложность указывается отдельно;
  • конкретное изменение, позволяющее познакомиться с одной возможностью Airflow;
  • подсказка по необходимости;
  • "Что должно получиться" с указанием места проверки;
  • для экспериментов с ошибками - способ вызвать ошибку и вернуть нормальное поведение;
  • при необходимости один короткий вопрос о причине наблюдаемого результата.

Для ветвления и обработки ошибок проверяются статусы отдельных задач и всего DAG Run. Формулировка "всё зеленое" не подходит для сценария с ожидаемыми пропусками или ошибками. Проверка результата не должна требовать ожидания недельного расписания или неограниченного числа случайных запусков.

Распределение содержания

Распределение уточнено после разбора 25 исходных заданий. Номера итоговых упражнений указаны в рабочей таблице ниже; правила прохождения находятся в разделе "Согласованные решения".

Блок Основная практика Возможное усложнение по желанию
Первый DAG Запуск, граф, логи, добавление задачи по образцу, зависимости, знакомство с расписанием Дополнительные эксперименты с ограничениями запусков
SQL и Connections Выполнение SQL, смена подключения, наблюдение результата и ошибки подключения Дополнительные отчеты и расширение модели данных
Файлы и преобразования Проследить путь файла между задачами, изменить простое преобразование или проверку Новые поля, отчеты, обработка по отделам
CSV → PostgreSQL → DQ Проследить загрузку, найти путь к файлу в XCom, добавить проверку, увидеть корректные и ошибочные данные Расширение схемы с согласованным изменением загрузчика и DQ, общая сводка проверок
Пример ETL Прочитать граф с параллельными задачами, найти промежуточные и итоговые результаты Новый источник, расширенная аналитика, архивирование
Ветвление и Variables Управляемо выбрать ветку, увидеть skipped, понять слияние веток Третья ветка и полноценная обработка разных форматов
Ошибки и повторы Вызвать ошибку, увидеть повтор и успешное завершение, найти причину в логах Экспоненциальная задержка, разные исключения, эскалация
Пулы, XCom и TaskGroup Ожидание слотов, новая метрика XCom, группировка существующих задач XCom в Bash-шаблоне; настоящая отправка писем на примере с ошибками

Чтение и изменение XCom не должно зависеть от выполнения дополнительного задания по резервному копированию. Для знакомства с пулами достаточно готовых задач с наблюдаемой длительностью; написание механизма резервного копирования не является целью такого эксперимента.

Разбор 25 исходных заданий

Номера слева относятся к версии 13e3102, номера справа - к новой редакции educational-tasks.md. Состав основной практики покрывает темы глав 4-9; главы 1-3 дают контекст перед запуском. Обработка по интервалам и самостоятельный проект остаются следующей ступенью программы.

Исходное задание Возможность Вход и зависимости Решение и причина Новое место Наблюдаемый результат
hello_world / 1 PythonOperator, зависимости Исходный DAG Основное: небольшое изменение графа 1.1 Новая задача и ее сообщение видны в UI
hello_world / 2 Расписание, ограничения запусков После 1.1 Разделить: расписание основное, конкуренция по желанию 1.3, 1.A Видно расписание; второй запуск ожидает при лимите 1
hello_world / 3 BashOperator После 1.1 Основное: другой оператор и файл 1.2 Файл содержит ожидаемый текст
sql_basic / 1 SQL в задаче, схема таблицы Исходный SQL-DAG и training Разделить: UPDATE основное, схема по желанию 2.2, 2.A Возраст изменен; дополнительная колонка заполнена
sql_basic / 2 PostgresHook и отчет После 2.2, таблица с тремя строками По желанию: дополнительная обработка 2.B Файл: 3 студента, средний возраст 23.33 после UPDATE
sql_basic / 3 Connections и диагностика Учебная БД, собственный Conn Id Основное; вместо неопределенного обработчика - найти и исправить ошибку подключения 2.1 Ошибка видна в логах, после исправления запуск успешен
file_operations / 1 Генерация, валидация Исходный файловый DAG Разделить: простая трансформация основная, новые поля по желанию 3.1, 3.A 100 обработанных строк; поля и фильтр проверены отдельно
file_operations / 2 Отчет по отделам Требует 3.A По желанию; график исключен, поскольку требует отдельной зависимости и не знакомит с новой возможностью Airflow 3.B Сумма численности отделов равна числу строк входа
file_operations / 3 Параллельность, DQ, retries Требует 3.A По желанию; параллельность также видна в основном ETL-примере 3.C Раздельные файлы покрывают все отделы, сборка читает их
csv_to_postgres / 1 Проведение поля через загрузку После основной загрузки и DQ По желанию: согласовать все четыре SQL/CSV-участка и проверку схемы 4.A status заполнен; DQ проходит; исходная схема восстановлена
csv_to_postgres / 2 Специализированный оператор Базовая схема orders По желанию: сравнение двух реализаций уже знакомого действия 4.B После замены оператора загрузка и DQ успешны
csv_to_postgres_dq / 1 Новая проверка, ошибка данных Основная загрузка orders Основное: положительный и отрицательный сценарии 4.2 Отрицательная сумма вызывает failed; восстановление возвращает success
csv_to_postgres_dq / 2 Trigger Rules и итог DAG Run После 4.2 По желанию: запуск всех проверок и общая сводка 4.C Все проверки завершаются, итог сохраняет ошибку
data_processing / 1 Несколько источников Исходный ETL, свои CSV По желанию; основной разбор графа добавлен перед расширениями 5.1, 5.A После JOIN остаются 6 заказов и выручка 2105
data_processing / 2 Отчет pandas После основного запуска, products не нужен По желанию 5.B Топ заказов и средние сверяются с шестью исходными строками
data_processing / 3 Валидация, callback, архив После 5.1; поля продуктов необязательны По желанию с конкретной ошибкой и восстановлением 5.C При ошибке архив не создается; после исправления совпадает с результатом
branching / 1 Выбор ветки и слияние Исходный DAG, Variable branch_format Разделить: две управляемые ветки основные, третья по желанию 6.1, 6.A Выбранная ветка success, другая skipped, слияние success
branching / 2 Работа выбранной ветки с данными Два явно заданных входных файла По желанию; использовать XCom текущего запуска вместо старых файлов другой ветки 6.B Оба формата дают одинаковые агрегаты в отдельных запусках
branching / 3 Variables, неизвестный параметр После 6.1 Variable включена в основное; fallback объединен с третьей веткой 6.1, 6.A Неизвестное значение дает понятную ошибку либо review-ветку после расширения
error_handling / 1 Повторы и задержка Исходный DAG, Variable error_mode Разделить: один управляемый повтор основной, backoff по желанию 7.1, 7.2, 7.A Две попытки; с нулем повторов - failed
error_handling / 2 Типы ошибок и оповещение После 7.2 По желанию; локальный callback без внешней почты 7.B После исчерпания повторов есть сообщение с task_id и причиной
error_handling / 3 logging После 7.1 Основное небольшое дополнение вместо механической замены всех print 7.3 Собственные сообщения видны в логах
Дополнительные / 1 Пулы и слоты Готовый resource_management_dag, пул из 2 слотов Основной короткий эксперимент; резервное копирование заменено имитацией чтения 8.1 Задачи с весами 2 и 1 выполняются последовательно
Дополнительные / 2 XCom и Jinja После 8.1 Основная метрика; шаблон Bash по желанию 8.2, 8.A total_rows = 50, шаблон выводит то же значение
Дополнительные / 3 TaskGroup и алертинг После 8.2; для почты нужен SMTP Разделить: группировка основная, внешняя доставка по желанию 8.3, 8.B Группа раскрывается; XCom работает с полными task_id

Основной маршрут сохраняет изменения внутри блоков. Общие данные есть только в паре загрузка/DQ; изменение схемы вынесено после основных опытов, с обратным ALTER и возвратом списков колонок. Задания 3.B и 3.C явно зависят от дополнительного 3.A, но дальнейшая основная практика от этой ветки не зависит. Variables возвращаются к исходным значениям перед переходом дальше.

Найденные несогласованности и препятствия

Первичные находки подтвердились при чтении кода и выполнении. Ниже их итоговое состояние; подробные результаты приведены в протоколе.

Место Исходная проблема Итог
SQL DROP после вставки не готовил существующую таблицу к новой колонке; результат очищался до проверки. Исправлено: TRUNCATE перед вставкой, task_id truncate_table, три строки остаются в БД. В 2.A ALTER выполняется до запуска. Проверены UPDATE, email и отчет.
Загрузчик CSV Подсказка про status пропускала INSERT ... SELECT. Исправлено: перечислены четыре участка загрузчика и порядок полей CSV/COPY. Проверены значения статусов в БД, а не только наличие колонки.
Схема DQ Дополнительная колонка конфликтовала с ожидаемыми четырьмя. Исправлено: расширение идет после основного DQ; описаны обновление ожидания и возврат схемы. Оба состояния проверены.
Trigger Rules DQ После отказа обещан skipped. Исправлено на upstream_failed; подтверждены отказ проверки суммы и отказ схемы.
Обработчики ошибок chain связывал списки попарно. Исправлено: оба обработчика имеют обе рабочие задачи в непосредственных предшественниках. Проверены успех, повтор, отказ первой, второй и обеих задач, общий итог DAG Run.
Сводка DQ и алертинг Единственная успешная завершающая задача с all_done могла скрыть ошибку; письмо безусловно сообщало об успехе. Исправлено: сводка сверяет состояния и падает при неуспешной проверке. Уведомления назначены callbacks задачи и DAG. Проверены all_done, письма об отказе/успехе и сохранение результата при ошибке SMTP.
ETL Transform обходил результаты Extract, имитация называлась загрузкой в БД. Исправлен путь данных. Имитация сохранена и явно обозначена именем simulate_load и логом. Фильтрация Extract изменила отчет с 6/2105 на 4/2000.
Пулы Формулировка "не более двух задач" не показывала ограничение по весам. Добавлен готовый пример: в пуле из двух слотов веса 2+1 выполняются последовательно, 1+1 пересекаются по времени. Проверены оба варианта.
Ветвление, повторы и зависимости Случайность мешала наблюдать нужный случай; использовались неопределенные входы и результаты старых запусков. Исправлено: Variables управляют режимами; входы CSV/JSON заданы; слияние читает XCom текущего запуска; зависимости дополнительных упражнений указаны явно.
Логи callbacks Первоначальная инструкция отправляла все сообщения в docker compose logs scheduler. Уточнено после выполнения: callback оператора виден в последней попытке задачи, callback DAG в файле scheduler. Оба места проверены.

Технические источники: chain, статусы задач, итог DAG Run, пулы, COPY в PostgreSQL 16. Условия поиска логов уточнены по фактическому стенду 2.9.2.

Как проверять результат доработки

Результаты проверок сохранять в этом документе рядом с закрываемым этапом: проверенная версия/коммит, сценарий и исходное состояние, ожидаемый и фактический результат, способ проверки. Для длинных логов или снимков экрана достаточно ссылки на доступный артефакт. Версию Airflow сверять с фактическим окружением, а не только с тегом образа в Dockerfile.

Проверки разделяются по уровню доказательств:

  • Документы и исходники: все 25 исходных заданий учтены, ссылки работают, имена файлов/задач/таблиц совпадают, обязательность и зависимости согласованы.
  • Стенд: подтверждены версия Airflow и загрузка DAG без ошибок импорта; выполнены затронутые сценарии и проверены файлы/таблицы. Проверка синтаксиса Python не заменяет выполнение задач.
  • UI: студент действительно может найти указанные состояния, логи, XCom, граф и настройки; показанные результаты совпадают с текстом.
  • Прохождение: отдельно проверены основной маршрут и переходы после дополнительных заданий. Не выполненные проверки так и отмечаются; предполагаемое время не выдается за измеренное на студентах.

Эксперименты с изменением данных выполняются в изолированном учебном окружении. Проверка не должна затрагивать другие работающие стенды или несвязанные изменения пользователя.

Почему выбран этот формат

Одни метки сложности не разделяют смешанные упражнения и не объясняют условия продолжения. Полностью независимые задания увеличивают повторную подготовку. Отдельный сборник усложнений разрывает связь с исходным примером. Демонстрации без изменения кода дают меньше практики, а самостоятельный большой пайплайн дублирует цель последующих курсовых.

Выбранный формат сохраняет практику изменения кода и позволяет переходить к следующему блоку после знакомства с нужными возможностями Airflow.