Files

129 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Прием airports через PXF: материалы автора
Лабораторная [#9](https://git.dementev.space/ddmitry/airflow-greenplum/issues/9)
из [серии #8](https://git.dementev.space/ddmitry/airflow-greenplum/issues/8).
Студент работает по [инструкции в main](https://git.dementev.space/ddmitry/airflow-greenplum/src/branch/main/docs/assignment/pxf_airports.md).
Общие принципы программы находятся в [авторской заметке](labs_development.md).
## Место и самостоятельная часть
Работа идет после быстрого старта и знакомства с моделью, перед существующими
`ods.airplanes` и `ods.seats`. Входом служит прошедшая эталонная цепочка
до `dm.sales_report` на учебной `main`; пустые студенческие таблицы не мешают
начать работу. Полный `bookings_validate` не является условием входа.
Выбран `airports`: он небольшой, содержит ключ, многоязычные JSON и координаты,
а его готовая загрузка ODS дает наблюдаемый результат преобразования.
Студент удаляет внешний DDL из `sql/stg/airports_ddl.sql` и заменяет
`sql/stg/airports_load.sql` заглушкой. В базе удаляет внешний объект и все
снимки только `stg.airports`. Без очистки прошлые строки могли бы скрыть
отсутствие собственной загрузки.
Внутренний DDL, JDBC-конфигурация и DQ остаются готовыми. Добавлен готовый
`lab_pxf_airports`: восемь PostgresOperator выполняют существующие загрузки
и проверки четырех справочников. Студент задает
состав и порядок полей внешней таблицы, `LOCATION`, затем пишет получение
снимка с ключом и метками. Близкий пример — `airplanes`. Физическая организация
внутренней таблицы и самостоятельная оркестрация относятся к следующим работам.
## Устройство урока
Основной текст строится вокруг собственной загрузки и опытов с данными.
Сначала студент пишет SQL по требованиям и близкому примеру, затем
предполагает результат повторного выполнения и переименования аэропорта,
наблюдает данные и объясняет различия. Передача нового названия в ODS
показывает применение его работы в следующем слое.
Команды подготовки, первые действия Airflow, сверка и восстановление
находятся в раскрываемых блоках рядом с соответствующим действием.
Проверки остаются готовыми: написание собственной DQ относится к дальнейшим
заданиям. Результат студента — два SQL-файла и объяснение опытов; собирать
отчет из JSON, Run ID и логов не требуется.
Обозначения A/B/C, проверки намеренно неверной реализации и полный протокол
приемки относятся к авторским материалам. Они подтверждают пригодность
лабораторной, но не задают структуру урока. Одного сокращения формулировок
было бы недостаточно: оно сохранило бы последовательность сбора доказательств
вместо работы с собственной загрузкой. Демонстрационный разбор также
не дал бы предусмотренной программой самостоятельной практики.
## Полное решение
Эталон уже содержится в этой ветке:
- [airports_ddl.sql](../../sql/stg/airports_ddl.sql): шесть TEXT-полей,
`pxf://bookings.airports_data?PROFILE=JDBC&SERVER=bookings-db`,
`FORMAT 'CUSTOM' (formatter='pxfwritable_import')`.
- [airports_load.sql](../../sql/stg/airports_load.sql): чтение внешней таблицы,
`_load_id = '{{ run_id }}'`, две метки `now()`, защита `NOT EXISTS`
по паре `(_load_id, airport_code)`.
- [airports_dq.sql](../../sql/stg/airports_dq.sql): базовая обратная связь DAG.
- [airports_load.sql для ODS](../../sql/ods/airports_load.sql): выбор батча,
извлечение `ru` и замена текущего снимка.
Для воспроизведения автор может после вычитания вернуть два исходных файла
из сохраненной копии. В учебной ветке они также остаются готовыми при первом
запуске: вычитание выполняется самим студентом во время работы.
Скрывать ответ технически не требуется; самостоятельность проверяется
опытами и объяснением результата.
## Почему нужны эти проверки
Готовая [сверка в main](https://git.dementev.space/ddmitry/airflow-greenplum/src/branch/main/scripts/check_airports_snapshot.py)
экспортирует источник напрямую из Postgres, без внешней таблицы студента.
Поэтому неверный `LOCATION` не становится одновременно ошибкой загрузки
и ее контрольного источника. В JSON сохраняются все бизнес-поля, а не только
выбранное русское имя. Перезапись контрольного файла запрещена.
В STG проверяются ключи, отсутствие дублей внутри батча, все бизнес-поля,
`_load_id`, наличие `_load_ts` и `event_ts`. JSON сравнивается по содержимому,
чтобы порядок свойств не влиял на результат. В ODS проверяется вся таблица,
русские значения названий и точный STG `_load_id` у каждой строки.
Штатная DQ сверяет количество и обязательные поля, поэтому сама по себе
не отвергнет старое непустое название с правильным числом строк.
| Случай | Наблюдаемый результат |
|---|---|
| Вычитание | STG пуст; внешняя таблица отсутствует; независимая сверка отказывает |
| A | Все ключи и бизнес-поля совпадают с прямым экспортом источника |
| Повтор A | Clear только загрузки аэропортов, затем ее DQ в том же запуске; строки сохраняются, генератор не повторяется |
| Изменение источника | Сохранен исходный JSON одного аэропорта; изменен только `ru` |
| Неверная старая копия | A или его копия с новым `_load_id` не совпадает с контрольным источником B при равном числе строк |
| B | B содержит новое имя; A все еще совпадает с исходным экспортом |
| ODS | Все четыре справочника имеют B; resolver без `conf` выбирает B; ODS содержит B и новое имя |
| Восстановление C | Источник в точности равен исходному A; новый общий C проходит ODS → DDS → DM |
Для повторов A используется Clear отдельных задач. A/B/C создаются
через `lab_pxf_airports`: повтор снимка не требует нового транзакционного дня.
Это стало отдельной границей при подготовке опыта: полные запуски STG
привязывали каждый контроль справочника к длительной генерации Bookings.
Учебный DAG явно исключает генератор и транзакционные загрузки, но использует
те же SQL-файлы снимков. Основной `bookings_to_gp_stage` сохраняет свое поведение.
Автоматический resolver выбирает последний общий ID по времени готовности.
Наличие ID во всех таблицах не доказывает их полноту — нужны DQ и сверка.
Передача `stg_batch_id` через `conf` обошла бы автоматический выбор, поэтому
в проверочном опыте ODS запускается с пустым `conf`.
## Выход и переход
В `stg.airports` остаются A/B/C; старые снимки аэропортов удалены в начале.
В остальных справочниках остаются также снимки быстрого старта. Транзакционные
таблицы сохраняют данные подготовки. B сохраняет
учебное изменение как историю; последний общий C и текущий ODS содержат
восстановленные значения. Источник восстанавливается из постоянной таблицы
`public.lab9_airport_original`, поэтому закрытие psql не теряет копию.
Повтор UPDATE восстановления безопасен; таблица удаляется только после сверки.
Следующая работа берет общий C для `ods.airplanes` и `ods.seats`, без нового
STG. Затем сохраняется прежний маршрут измерений и витрин. Работы #10–#14
остаются отдельными задачами серии; эта лабораторная не добавляет их заглушки
и не меняет текущие требования к ним.
## Проверочный прогон
Команды, версии и наблюдения сохраняются в
[протоколе прогона](../reports/2026-09-22-pxf-airports.md).
Проверять нужно учебную `main`: полный `solution` заполняет дополнительные
таблицы и не подтверждает проходимость первой работы с учебными заглушками.