- Зачем:
- qa-plan утверждал «ВСЕ таблицы > 0», что неверно на main с 9 заглушками.
- Что:
- добавлена секция в intro со списком пустых таблиц на main.
- SQL-комментарии DDS/DM дополнены пометками заглушек.
- ожидание разделено на solution (все > 0) и main (эталонные > 0).
- Проверка:
- make test (4 passed, 14 skipped).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Шаг 5 плана main/solution split:
- Удалены внутренние документы с main: plans/, archive/, PRD,
assignment_design, pxf_bookings, bookings_tz, benchmarks, TODO.md
- AGENTS.md: убраны упоминания plans/archive, agent-dag-testing
- Починены 19 битых markdown-ссылок во всех оставшихся файлах
- bookings_ods_design: airplanes/seats помечены как студенческие,
обновлён DAG-граф (routes без зависимости от airplanes)
- bookings_dds_design: обновлено описание DQ факта (student SK)
- bookings_to_gp_dds: обновлена DQ-семантика для main
- qa-plan: уточнено — ods.airplanes/seats пусты by design на main
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Описания fact_flight_sales_load обновлены в bookings_dds_design,
bookings_to_gp_dds и db_schema: departure/arrival_airport_sk теперь
разрешаются через ods.routes → dim_airports, а не через dim_routes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Зачем:
- нужна стратегия ветвления и пошаговый план для финального этапа подготовки курсовой
- Что:
- создан `docs/plans/2026-03-12_main-solution-split.md` (v4, после 4 ревью Codex)
- стратегия: мерж в main → общие правки → ветка solution → заглушки на main
- solution как source of truth, однонаправленный поток solution → main
- план очистки docs для студентов (удалить plans/archive/PRD с main)
- открытый вопрос: детальный протокол синхронизации веток
- добавлена пометка статуса в архивный план routes-to-reference
- Проверка:
- просмотр `docs/plans/2026-03-12_main-solution-split.md`
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Зачем:
- make dwh-truncate очищал только dm.sales_report, остальные 4 витрины
сохраняли старые SK → DQ падал при перезагрузке DDS с новыми ключами.
- Что:
- добавлены route_performance, airport_traffic, monthly_overview,
passenger_loyalty в TRUNCATE блок DM.
- Проверка:
- make dwh-truncate + полный прогон пайплайна (STG→ODS→DDS→DM→validate).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Зачем:
- студент реализует 9 объектов DWH без автоматической обратной связи;
- ошибки (NULL в PK, дубли BK, сломанный SCD2) обнаруживались только на слое DM
через 2–3 слоя, где отладка многократно сложнее.
- Что:
- создан DAG bookings_validate.py — три параллельных TaskGroup (validate_ods,
validate_dds, validate_dm), schedule=None (только ручной trigger);
- создано 17 SQL-скриптов в sql/validate/: ODS BK coverage vs STG-батч,
согласованность _load_id между ods.airplanes и ods.seats, дубли BK, NULL в PK,
покрытие ODS→DDS для измерений (dim_routes требует открытой версии valid_to IS NULL),
SCD2 активный тест backup→mutate→student_load→check(5 инвариантов)→restore
(trigger_rule=all_done), проверка «дыр» между SCD2-версиями,
exists-чеки для 4 DM-витрин;
- добавлен класс TestBookingsValidate (5 smoke-тестов) в tests/test_dags_smoke.py.
- Проверка:
- make test — 4 passed, 14 skipped (DAG-тесты скипаются без Airflow, норма);
- ручной trigger bookings_validate в Airflow UI на solution-ветке — все таски зелёные.
- Зачем:
- план routes-to-reference выполнен, нужен план следующего этапа — валидационный DAG
- Что:
- перемещён docs/plans/2026-03-11_routes-to-reference.md → docs/archive/
- создан docs/plans/2026-03-12_validation-dag.md: структура DAG (17 SQL + DAG + smoke-тест),
активный тест SCD2 (цепочка тасков с безопасным откатом), прошёл 5 раундов ревью ChatGPT
- Проверка:
- make test
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Зачем:
- fact_flight_sales брал airport_sk через dds.dim_routes (студенческое задание SCD2);
на ветке main без реализованного dim_routes все airport_sk были NULL,
и эталонные витрины sales_report/airport_traffic становились бесполезны.
- Что:
- fact_flight_sales_load.sql: добавлен subquery ods_rte (ROW_NUMBER по ods.routes),
dep/arr airport_sk теперь через ods.routes (эталон); airplane_sk — через dim_routes (point-in-time).
- analyst_spec.md: удалены STG-задания (1.1–1.3) и ods.routes (2.3), добавлены секции
«Почему STG уже реализован» и «Пересчёт факта», исправлен ODS intro, перенумерованы части.
- assignment_design.md: обновлены таблицы эталон/задание, порядок выполнения; убраны
validate_stg и check_ods_routes_rowcount из структуры валидационного DAG.
- db_schema.md: статус уточнён («реализовано в ветке solution»), добавлена оговорка
о заглушках на main, DQ-контракт дополнен примечанием.
- Проверка:
- make test → 4 passed, 9 skipped.
- ручная проверка: TRUNCATE dds.fact_flight_sales → перезапуск DDS DAG →
COUNT(departure_airport_sk) должен равняться COUNT(*).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Зачем:
- обнаружен конфликт между дизайном БД и планом курсового задания:
эталонный пайплайн неработоспособен на main без студенческих измерений.
- Что:
- создан docs/plans/2026-03-11_routes-to-reference.md (v4, после 3 раундов ревью).
- добавлен бэклог PXF-практикума в assignment_design.md (раздел 6).
- Проверка:
- прочитать план, убедиться в согласованности формулировок.
- Зачем:
- db_schema.md не отражала DM-слой и содержала неточности в метаданных таблиц.
- architecture_review.md устарел: все P0–P2 выполнены, P3 отложены и покрыты другими документами.
- Что:
- db_schema.md переработана: Mermaid-диаграмма потоков перенесена в начало, добавлен DM-слой, STG/ODS/DDS/DM представлены компактными таблицами.
- исправлены неточности: dim_calendar (AO Column → AO Row), dim_tariffs (INSERT-only → SCD1), ODS добавлено поле event_ts.
- architecture_review.md перенесён из docs/design/ в docs/archive/, статус обновлён на «завершён».
- Проверка:
- открыть docs/design/db_schema.md и убедиться, что диаграмма в начале файла, DM-слой отражён.
- Зачем:
- необходимо гарантировать проверку логики SCD2 в учебном проекте, так как исходные данные статичны и не вызывают срабатывание SCD2 естественным образом.
- Что:
- добавлен раздел "Активная проверка SCD2" в дизайн задания (assignment_design.md).
- описан алгоритм с использованием временных таблиц для тестирования закрытия старых и открытия новых версий записей.
- Проверка:
- визуальный осмотр обновленного раздела в docs/design/assignment_design.md.
- Зачем:
- файлы планов именовались хаотично (микс snake_case/kebab-case, без дат),
из-за чего архив не сортировался хронологически.
- Что:
- установлен формат YYYY-MM-DD_краткое-описание.md для docs/plans/ и docs/archive/.
- переименованы 6 архивных файлов по новой конвенции (git mv).
- конвенция зафиксирована в AGENTS.md (секция «Карта проекта»).
- Проверка:
- ls docs/archive/ — все файлы начинаются с даты в kebab-case.
- Зачем:
- документация трёх DAG-ов была значительно беднее эталона (bookings_to_gp_stage.md):
отсутствовал пошаговый разбор задач, SQL-пути и ASCII-графы зависимостей.
- Что:
- добавлены секции "Как это работает внутри" с таблицами task_id → SQL-файл → паттерн.
- добавлены ASCII-графы зависимостей в ODS и DDS (в DM уже был).
- исправлено описание паттернов ODS: явно разделены TRUNCATE+INSERT для AO snapshot-справочников и SCD1 UPSERT для транзакционных таблиц.
- исправлено описание fact_flight_sales: убрана неточная отсылка к late-arriving dimensions, добавлено объяснение defensive LEFT JOIN и точных DQ-правил (0% / 1%).
- добавлена таблица grain и описание стратегий загрузки для каждой DM-витрины.
- план улучшений перенесён в docs/archive/.
- Проверка:
- визуально: открыть каждый docs/bookings_to_gp_*.md и убедиться, что секции присутствуют.
- Зачем:
- после реструктуризации docs/ агенты не знали о новых каталогах
design/, reference/, plans/, archive/, assignment/.
- Что:
- в раздел «Карта проекта» добавлена строка со структурой docs/.
- Проверка:
- читаемость AGENTS.md, раздел 2.
- Зачем:
- Этап «подготовка main» не должен идти раньше ТЗ и валидационного DAG —
нельзя удалять рабочий пайплайн до того, как всё создано и протестировано.
- Что:
- Этапы 2-5 переупорядочены: сначала ТЗ от аналитика, затем валидационный DAG,
в конце — подготовка main и создание ветки solution.
- Этапы 2 и 5 (подготовка main + solution) объединены в один финальный этап.
- Добавлены пояснения «Делаем пока полный пайплайн работает» к каждому этапу.
- Проверка:
- Читаемость TODO.md.
- Зачем:
- docs/internal/ превратился в свалку: дизайн-документы, ревью, планы и справочники лежали вперемешку.
- архивные планы были неотличимы от живых документов.
- Что:
- docs/internal/ удалён; файлы распределены по docs/design/, docs/reference/, docs/archive/, docs/plans/, docs/assignment/.
- educational-tasks.md убран из корня в архив (устарел).
- обновлены все перекрёстные ссылки в AGENTS.md, TODO.md, README.md, docs/README.md и внутри design/reference/.
- актуализированы architecture_review.md (статус DM-слоя), db_schema.md (DM-слой), TESTING.md, dag_execution_order.md, pxf_bookings.md.
- добавлены заглушки docs/assignment/README.md и docs/plans/README.md.
- Проверка:
- make test && make lint
- rg 'docs/internal' --glob '!docs/archive/*' — должно быть пусто.
- Зачем:
- STG-слой использовал legacy-имена (batch_id, load_dttm, src_created_at_ts),
тогда как ODS/DDS/DM уже работали с каноном (_load_id, _load_ts, event_ts).
Студент видел разные имена для одного понятия — это убрано.
- Что:
- переименованы колонки в 9 STG DDL: batch_id→_load_id, load_dttm→_load_ts,
src_created_at_ts→event_ts; добавлен NOT NULL для _load_id во всех таблицах.
- обновлены 9 STG Load, 9 STG DQ, 9 ODS Load, 9 ODS DQ (INSERT/SELECT/WHERE).
- обновлены DAG-файлы bookings_to_gp_stage.py и bookings_to_gp_ods.py
(встроенный SQL резолвера, комментарии; Python-идентификаторы не тронуты).
- обновлены тесты и ~15 документов (naming_conventions, PRD, db_schema,
design-docs, qa-plan, README, TESTING и др.).
- Проверка:
- grep -rn 'load_dttm\|src_created_at_ts' sql/ airflow/ tests/ — 0 совпадений.
- make test — 4 passed.
- e2e-etl: day1 прошёл полностью, day2 стартовал без ошибок.
- Зачем:
- ветка содержала устаревшие ссылки, артефакты CSV-пайплайна и метки «черновик»
для полностью реализованных слоёв STG→ODS→DDS→DM.
- Что:
- AGENTS.md: заменена фраза «в будущем» на перечисление реальных слоёв ODS/DDS/DM.
- TESTING.md: удалены две строки про каталог data/ (артефакт CSV-пайплайна).
- README.md: список документации заменён на кликабельные markdown-ссылки, добавлены STG и DM DAG.
- docs/README.md: добавлен DM DAG в «Быстрый путь», DM design в «Технические детали»; убраны метки «(черновик)».
- docs/internal/bookings_stg_design.md: убран заголовок «черновик», исправлены описания слоёв и DDL.
- docs/internal/PRD.md: битая ссылка на analyst_spec.md заменена текстом с пометкой TODO.
- TODO.md: ссылка на plans/ обновлена на docs/internal/bookings_db_issues.md.
- docs/bookings_to_gp_dm.md: создан новый документ по аналогии с DDS doc (5 витрин, граф, DQ, ошибки).
- plans/ и docs/chore/: каталоги удалены (планы выполнены, история сохранена в git).
- Проверка:
- make lint && make test — прошло чисто.
- grep -n "черновик|data/|в будущем|plans/" — пустой результат.
- Зачем:
- агент использовал CLI (`docker exec ... airflow dags unpause`) вместо REST API,
что приводило к зависанию DAG'ов в статусе `queued`.
- Что:
- e2e-etl-test-protocol: явный запрет на CLI-команды, REST API как основной метод,
шаблон unpause+trigger для каждого слоя, пример проверки статуса через API.
- agent-dag-testing: убрана оговорка «если он новый» — unpause обязателен всегда.
- TODO: пункт «стенд поднимается на чистой машине» отмечен выполненным.
- Проверка:
- прочитать docs/e2e-etl-test-protocol.md и docs/agent-dag-testing.md.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Зачем:
- план содержал неверные имена полей и формулы, которые давали ошибки при выполнении.
- Что:
- `_batch_id` → `batch_id` в запросах снапшот-таблиц STG (реальное имя колонки).
- формула SCD2-маршрутов: `COUNT(DISTINCT route_no)` вместо `route_no || '-' || validity`
(DDS берёт один route_no с последним validity через rn=1).
- `ticket_price` → `price`, `boarding_seq IS NOT NULL` → `is_boarded = TRUE`
(реальные колонки dds.fact_flight_sales).
- Блок 2: добавлено пояснение, что STG-DAG всегда генерирует новый день,
поэтому тест идемпотентности — только ODS/DDS/DM без повторного запуска STG.
- Блок 5.2: уточнено, что ODS намеренно использует batch_id из STG вместо run_id
для сквозного lineage — это паттерн, а не баг.
- Проверка:
- все SQL-запросы из плана выполнены на стенде без ошибок.
- Зачем:
- бенчмарк на i7-11800H / WSL2 показал, что jobs=1 генерирует +1 день за ~3 мин,
а jobs=2 — за ~9 мин из-за lock contention на gen.events FOR UPDATE SKIP LOCKED.
Тюнинг PG (shared_buffers, work_mem) и synchronous_commit=off не влияют.
- Что:
- дефолт BOOKINGS_JOBS изменён с 2 на 1 в Makefile и .env.example.
- добавлен docs/internal/bookings_generation_benchmark.md с полной матрицей экспериментов.
- обновлены комментарии и bookings/README.md.
- Проверка:
- make bookings-init && time make bookings-generate-day (~3 мин).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Зачем:
- make bookings-generate-day зависал на 35+ мин в WHILE busy() LOOP при BOOKINGS_JOBS=2,
а VACUUM ANALYZE всей БД внутри process_queue() добавлял минуты к каждому инкременту.
- Что:
- заменён опрос busy() (pg_stat_activity) на dblink_is_busy() — прямая проверка
состояния каждого dblink-соединения, без зависимости от application_name и state.
- перед continue() удаляются VACUUM-ивенты из gen.events — они бессмысленны для +1 дня.
- Проверка:
- make bookings-init && make bookings-generate-day BOOKINGS_JOBS=2 (~5-8 мин, без зависания).
- DAG bookings_to_gp_stage: все 20 тасков success.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Зачем:
- генерация с нуля занимала часы, boarding_passes были пустыми, данные
пропадали после docker compose down/up.
- Что:
- обновлён demodb до коммита 866e56f, добавлен патч install_connstr_no_hardcode.
- BOOKINGS_INIT_DAYS увеличен до 60, BOOKINGS_JOBS по умолчанию 2.
- добавлен seed-дамп bookings/seed/demo.sql.xz (42 MB, xz вместо 7z).
- make bookings-init восстанавливает из дампа (~18 сек) и применяет GUC из .env.
- make bookings-generate — генерация с нуля для разработчиков.
- generate_next_day.sql: COMMIT после continue(), pg_sleep(3) для jobs>1, synchronous_commit=on + CHECKPOINT.
- bookings-check-jobs: добавлена валидация нечисловых значений BOOKINGS_JOBS.
- bookings-init теперь вызывает bookings-check-jobs как prerequisite.
- синхронизированы внутренние документы (коммит demodb, init_days=60).
- Проверка:
- make bookings-init && make bookings-generate-day BOOKINGS_JOBS=2.
- make test.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Зачем:
- зафиксировать найденные проблемы demodb и план системной проверки эталона
до начала подготовки ветки main для студентов.
- Что:
- добавлен qa-plan.md — 6 блоков проверки пайплайна (чистый прогон,
идемпотентность, инкремент, многодневный, статика, граничные случаи).
- добавлен bookings_db_issues.md — 3 бага demodb (gen.connstr без credentials,
init_days=1 недостаточно, boarding_passes всегда пустая) и UX-проблема
с временем генерации.
- Проверка:
- документы, проверка не требуется.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Зачем:
- Пример базовой загрузки CSV перенесен в отдельный репозиторий `airflow-manual` для разделения учебных треков.
- Что:
- удалены DAG-файлы `csv_to_greenplum` и вспомогательные скрипты `helpers/greenplum.py`, `orders_ddl.sql`.
- из `docker-compose.yml` и `.env.example` удалены переменные и тома (`airflow_data`), необходимые для CSV.
- очищена документация (`README.md`, `TESTING.md`, `educational-tasks.md`) и тесты (`test_dags_smoke.py`, `conftest.py`).
- отмечен выполненным 'Этап 1' в `TODO.md`.
- Проверка:
- `make test` проходит успешно (smoke-тесты оставшихся DAG-ов не затронуты).
- Зачем:
- PRD не должен быть трекером задач, у каждого документа своя роль
- Что:
- TODO.md реструктурирован: добавлен план подготовки курсовой (5 этапов с рекомендациями по инструментам), выполненные задачи перенесены в отдельную секцию
- PRD.md: раздел «План работ» заменён ссылкой на TODO.md, убраны решённые вопросы
- Проверка:
- просмотр TODO.md и docs/internal/PRD.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Зачем:
- необходим единый документ с требованиями для разработки ETL-процессов.
- Что:
- создан файл docs/internal/PRD.md с описанием архитектуры, требований к данным и сроков.
- Проверка:
- просмотр файла docs/internal/PRD.md.
- Зачем:
- необходимо синхронизировать документацию с фактически выполненными изменениями в коде.
- Что:
- отмечена как выполненная задача по явному указанию storage type для всех таблиц.
- обновлено обоснование для dds.dim_calendar (AO Row из-за малой ширины таблицы).
- отмечен как выполненный рефакторинг hashdiff в dim_routes_load.sql.
- Проверка:
- визуальная сверка docs/internal/architecture_review.md с файлами в sql/dds/ и sql/ods/.
- Зачем:
- старая инструкция была неполной (без ODS/DDS/DM) и содержала избыточные требования.
- Что:
- переписан docs/agent-dag-testing.md с фокусом на итеративную разработку и Airflow REST API.
- добавлены шаги по отладке упавших задач (логгирование через CLI) и проверке DWH слоев.
- Проверка:
- визуальная проверка текста руководства на соответствие актуальному пайплайну.
- Зачем:
- улучшение производительности аналитических запросов и упрощение витрин согласно принципам Kimball Star Schema.
- Что:
- в dds.dim_routes добавлены денормализованные поля городов и моделей самолетов.
- в скрипт загрузки dim_routes_load.sql добавлена фаза refresh для актуализации атрибутов.
- загрузка dm.route_performance упрощена до 1 JOIN к измерению маршрутов.
- обновлен DAG bookings_to_gp_dds и smoke-тесты структуры графа.
- в документации (db_schema.md) отражены денормализация и lineage версий.
- в dim_routes_load.sql исправлено затирание _load_id при refresh исторических версий.
- Проверка:
- make test (smoke-тесты структуры DAG проходят успешно).
- Зачем:
- необходимо упростить витрину dm.route_performance с 4-JOIN до 1-JOIN;
- привести измерение в соответствие с принципом Кимбалла («самодостаточное измерение»).
- Что:
- добавлена задача в TODO.md с описанием цели денормализации;
- создан детальный план реализации в docs/internal/dim_routes_denormalization_plan.md.
- Проверка:
- просмотр файлов TODO.md и docs/internal/dim_routes_denormalization_plan.md.
- Зачем:
- предоставить студентам полный набор аналитических витрин с примерами различных паттернов (UPSERT, Full Rebuild, UNION ALL, двухуровневая агрегация).
- Что:
- реализованы витрины: sales_report, route_performance, passenger_loyalty, airport_traffic, monthly_overview.
- исправлен баг в route_performance_load.sql: добавлены JOIN к dim_airports и dim_airplanes для корректной денормализации атрибутов.
- обновлен скрипт e2e_etl.sh: добавлена верификация всех 5 витрин и проверка бизнес-логики (load factor).
- обновлены DAGи, тесты и главный DDL скрипт.
- Проверка:
- автоматизированный прогон e2e_etl.sh через REST API Airflow.
- Зачем:
- необходимо продемонстрировать студентам работу с одной сущностью в разных ролях (вылет/прилет) через UNION ALL.
- Что:
- созданы DDL, Load и DQ скрипты для витрины dm.airport_traffic (пассажиропоток аэропортов).
- реализован паттерн Unpivot через UNION ALL для консолидации метрик вылета и прилета в одном разрезе.
- внедрена инкрементальная загрузка по затронутым датам (HWM) с честным подсчетом рейсов через COUNT(DISTINCT).
- добавлены подробные комментарии к колонкам выручки, предупреждающие о риске двойного счета.
- обновлены DAGи bookings_dm_ddl и bookings_to_gp_dm для включения витрины в общий пайплайн.
- Проверка:
- визуальный аудит SQL-кода на предмет использования airport_bk и корректной агрегации по ролям.
- наличие DQ-инварианта total_passengers = departures + arrivals.
- верификация блока UPDATE: теперь обновляются и денормализованные атрибуты (city, airport_bk).
- Зачем:
- необходимо продемонстрировать студентам метод инкрементального пересчета "затронутых ключей" для больших справочных витрин.
- Что:
- созданы DDL, Load и DQ скрипты для витрины dm.passenger_loyalty (лояльность пассажиров).
- реализован расчет моды (самый частый тариф) через PostgreSQL-специфику DISTINCT ON.
- внедрена корректная агрегация SCD2-измерений (unique_routes) по бизнес-ключу route_bk.
- настроено Heap-хранилище (WITH appendonly=false) для эффективного выполнения UPSERT.
- обновлены DAGи bookings_dm_ddl и bookings_to_gp_dm для включения новой витрины в конвейер.
- Проверка:
- визуальный аудит SQL на предмет использования p.passenger_id (BK) и r.route_bk.
- наличие учебной DQ-проверки ссылочной целостности и инварианта дат (first <= last).
- проверка параллельности задач в Airflow DAG.
- Зачем:
- необходимо продемонстрировать студентам альтернативный паттерн загрузки (Full Rebuild) и использование AO Column Store в Greenplum.
- Что:
- созданы DDL, Load и DQ скрипты для витрины dm.route_performance (эффективность маршрутов).
- реализована агрегация по бизнес-ключу route_bk для корректной обработки SCD2-измерений.
- настроен формат хранения AO Column Store с компрессией zstd (уровень 1).
- обновлены DAGи bookings_dm_ddl и bookings_to_gp_dm для параллельной оркестрации новой витрины.
- Проверка:
- визуальный аудит SQL-кода на соответствие naming_conventions.md.
- проверка структуры DAG в Airflow (параллельные ветки load -> dq).
- наличие бизнес-инварианта total_boarded <= total_tickets в DQ-скрипте.
- Зачем:
- необходимо визуализировать выбор типа хранения (Heap vs Append-Only) для учебных целей.
- автоматизировать проверку всей цепочки DWH для исключения ручных ошибок.
- сделать процесс отладки прозрачным и наглядным через стандартные инструменты Airflow.
- Что:
- внедрена клауза WITH (appendonly=...) во все DDL; ODS-справочники переведены на AO Row и TRUNCATE+INSERT.
- создан скрипт scripts/e2e_etl.sh для полного прогона ETL (DDL + 2 дня данных) через REST API.
- исправлены баги типизации (INTEGER[]), именования полей (amount, passenger_id) и удалены фантомные колонки (contact_data).
- обновлен e2e-etl-test-protocol.md: добавлен раздел по отладке, чтению логов и перезапуску задач через API.
- исправлены pytest-контракты под новую логику загрузки.
- Проверка:
- успешный прогон `make e2e-smoke` (полный цикл от очистки до витрины).
- Зачем:
- зафиксировать новые приоритеты по тестированию ETL и стабильности источника.
- Что:
- добавлены два новых пункта в backlog мейнтейнеров в TODO.md.
- уточнён статус файла, чтобы он отражал наличие открытых задач.
- Проверка:
- git diff --cached -- TODO.md.
- Зачем:
- зафиксировать новые приоритеты по тестированию ETL и стабильности источника.
- Что:
- добавлены два новых пункта в backlog мейнтейнеров в TODO.md.
- уточнён статус файла, чтобы он отражал наличие открытых задач.
- Проверка:
- git diff --cached -- TODO.md.
- Зачем:
- zstd (level 1) является современным стандартом для Greenplum 6.0+, обеспечивая более высокую скорость декомпрессии и лучшее сжатие.
- Что:
- обновлены все DDL стейджинга (STG) и базовых таблиц.
- обновлена архитектурная документация (ADR-3) и планы реализации.
- исправлены примеры кода в Airflow DAG и описании ETL.
- Проверка:
- успешное выполнение CREATE TABLE с новыми параметрами в Greenplum 6.27.1.
- Зачем:
- формализация проверки всей цепочки ETL (STG -> ODS -> DDS -> DM).
- Что:
- создан docs/e2e-etl-test-protocol.md и sql/truncate_gp.sql.
- в Makefile добавлена команда dwh-truncate.
- start_date во всех DAG изменен на 2017-01-01.
- Проверка:
- выполнение make dwh-truncate и прогон DAG.
- Зачем:
- исправление критических ошибок P0 (гонка HWM, ошибки в SQL CTE, непоследовательный lineage).
- использование временных таблиц делает код более читаемым для студентов и производительным для Greenplum.
- Что:
- в sql/ods/ (bookings, tickets, segments, boarding_passes, flights) выборка дельты вынесена в CREATE TEMP TABLE.
- HWM теперь вычисляется один раз, устраняя гонку между UPDATE и INSERT.
- во всех стейтментах используется оригинальный batch_id из STG для _load_id.
- поле _load_ts в ODS теперь берется из STG (load_dttm), что делает HWM-сравнение корректным.
- Проверка:
- визуальный аудит SQL-логики.
- Зачем:
- необходимо зафиксировать выполнение критической задачи (P0) в плане работ.
- Что:
- в архитектурном ревью пункт "ODS batch resolver теряет данные" отмечен как выполненный.
- Проверка:
- визуальная проверка docs/internal/architecture_review.md.
- Зачем:
- зафиксировать принятые архитектурные решения с обоснованием для менти,
чтобы студенты понимали границы учебных упрощений и реальную практику.
- Что:
- ADR-1: города/страны/модели — атрибуты измерений (star vs snowflake).
- ADR-2: партиционирование не используем (учебные объёмы), с примером
exchange partition и контекстом импортозамещения (Teradata/Exadata → GP).
- ADR-3: явный storage type для каждой таблицы — AO Column для write-once,
AO Row для snapshot-справочников (TRUNCATE+INSERT), heap для UPDATE-таблиц.
- добавлена задача P2 по реализации ADR-3, обновлена сводка трудозатрат.
- Проверка:
- cat docs/internal/architecture_review.md | grep "ADR-".
- Зачем:
- текущая реализация ODS batch_id теряла данные транзакционных таблиц, если между запусками ODS STG успевал отработать дважды (брался только последний батч).
- Что:
- изменены скрипты загрузки транзакционных таблиц (bookings, tickets, flights, segments, boarding_passes) для использования паттерна HWM по _load_ts вместо фильтрации по конкретному батчу.
- обновлен комментарий в DAG bookings_to_gp_ods, объясняющий разное поведение для справочников и транзакционных данных.
- сохранено использование оригинального batch_id из STG для поля _load_id в слое ODS для сквозного трассирования.
- Проверка:
- запуск пайплайнов и проверка, что все батчи загружаются из STG в ODS без потерь.
- Зачем:
- закрыты задачи P0 и P1 из ревью архитектуры для повышения понятности стенда для студентов.
- Что:
- исправлен distribution key для airport_traffic в дизайн-документе.
- добавлены комментарии о генерации SK и отсутствии SK в фактах.
- создан документ docs/dag_execution_order.md с описанием порядка запуска DAG-ов.
- объяснена логика late-arriving dimensions и batch resolver.
- добавлена legacy-пометка для хелпера greenplum.py.
- Проверка:
- визуальная проверка добавленных комментариев и новых файлов.
- Зачем:
- зафиксировать оценку учебной ценности текущей конструкции (STG→ODS→DDS→DM)
и сформировать backlog задач для доработки стенда.
- Что:
- создан docs/internal/architecture_review.md с анализом 9 сильных сторон
и приоритизированным списком замечаний (P0–P3) с чеклистом задач.
- Проверка:
- cat docs/internal/architecture_review.md.
- Зачем:
- дизайн-документ описывал устаревший batch-driven подход и не фиксировал паттерн TEMP TABLE, используемый в реализации.
- Что:
- заменено описание загрузки всех UPSERT-витрин на HWM-инкрементальность через _load_ts.
- добавлена секция «Общий паттерн загрузки UPSERT-витрин» с SQL-скелетом и таблицей применимости.
- в секции «Учит» каждой витрины добавлены паттерны HWM и TEMP TABLE.
- Проверка:
- визуальная проверка docs/internal/bookings_dm_design.md.
- Зачем:
- фильтр `_load_id = '{{ run_id }}'` использовал run_id DM-DAG-а, который не совпадает с run_id DDS-DAG-а, записанным в факты — витрина не находила дельту.
- Что:
- load: заменён _load_id-фильтр на HWM-подзапрос `_load_ts > MAX(_load_ts)` из dm.sales_report.
- dq: источник затронутых дат переключён с DDS на саму витрину (где _load_id уже корректный).
- Проверка:
- `make test` — smoke-тесты зелёные.
- запуск `bookings_to_gp_dm` в Airflow после загрузки DDS.
- Зачем:
- жесткая привязка инкремента к логической дате Airflow ({{ ds }}) приводила к пустой витрине при обработке исторических и "опоздавших" (late-arriving) данных.
- Что:
- изменена фильтрация в скрипте загрузки витрины: теперь динамически определяются даты, затронутые текущим батчем (через _load_id).
- обновлены DQ-проверки для валидации только тех дат, которые были изменены в рамках запущенного батча.
- в дизайн-документ добавлено описание паттерна работы с late-arriving facts для студентов.
- Проверка:
- запуск пайплайна "с нуля" за логическую дату 2024-01-01 приводит к корректному расчету агрегатов для исторических данных 2017 года (>8000 строк).
- Зачем:
- файл позволяет AI-агентам быстро находить и использовать контекст из AGENTS.md
- Что:
- создан файл GEMINI.md с ссылкой на @AGENTS.md
- Проверка:
- cat GEMINI.md
- Зачем:
- источник хранит мультиязычные названия как JSON ({"en": "...", "ru": "..."}),
- для упрощения downstream-логики (DDS/DM) нужны чистые строки на одном языке.
- Что:
- добавлен парсинг JSON с извлечением поля 'ru' в sql/ods/airports_load.sql
(airport_name, city, country).
- добавлен парсинг JSON с извлечением поля 'ru' в sql/ods/airplanes_load.sql
(model).
- обновлена документация docs/internal/bookings_ods_design.md с примечаниями
о нормализации.
- обновлены тестовые данные в tests/test_ods_snapshot_integration.py для
соответствия JSON-формату STG.
- Проверка:
- uv run make test (15 passed).
- SELECT airport_name FROM ods.airports → "Аль-Баха" (вместо JSON).
- Зачем:
- зафиксировать архитектуру 5 витрин DM перед реализацией и отдать на ревью.
- Что:
- создан docs/internal/bookings_dm_design.md с описанием всех витрин, DAG-структуры, DQ-проверок и порядка реализации.
- Проверка:
- cat docs/internal/bookings_dm_design.md.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Зачем:
- dq_ods_segments падал на непустых батчах из-за orphan flight_id в ods.segments.
- Что:
- доработан sql/ods/flights_load.sql: добавлено добирание рейсов из истории stg.flights для flight_id из stg.segments текущего batch.
- добавлен контрактный тест в tests/test_ods_sql_contract.py на покрытие flight_id из segments.
- обновлена документация DAG в docs/bookings_to_gp_ods.md.
- Проверка:
- make test.
- airflow dags trigger bookings_to_gp_ods -c '{"stg_batch_id":"manual__2026-01-18T18:47:18.316091+00:00"}'.
- Зачем:
- подготовлен учебный Star Schema слой для перехода от ODS к аналитике и витринам.
- Что:
- добавлены 21 SQL-файл для DDS (DDL/LOAD/DQ) с SCD1/SCD2 и фактом `fact_flight_sales`.
- добавлены DAG `bookings_dds_ddl` и `bookings_to_gp_dds`, а также smoke-тесты структуры DAG.
- обновлены `sql/ddl_gp.sql` и документация (`README`, `docs/*`, `db_schema`) под поток `stg -> ods -> dds`.
- Проверка:
- make test.
- Зачем:
- синхронизировать db_schema.md с фактическим состоянием репозитория и текущим DDS-планом.
- Что:
- обновлён статус слоёв: STG/ODS отмечены как реализованные, DDS как слой в проектировании.
- приведены к актуальному виду DDS-объекты и нейминг (`dds.dim_*`, `dds.fact_flight_sales`, `dds.dim_routes` SCD2).
- обновлены mermaid-диаграмма, обучающие пояснения, TODO, связанные документы и история изменений.
- Проверка:
- git diff -- docs/internal/db_schema.md
- Зачем:
- устранить противоречия и пробелы в плане DDS перед реализацией.
- Что:
- HIGH: факт теперь использует point-in-time SCD2 lookup для routes,
UPDATE факта не перезаписывает dimension SK (историчность сохранена).
- MEDIUM: явная политика NULL FK в факте (3 группы: обязательные,
зависят от маршрута, зависят от расписания) + DQ с порогом 1%.
- MEDIUM: добавлены DQ-проверки SCD2 интервалов (valid_from < valid_to,
нет перекрытий версий).
- MEDIUM: DQ факта теперь проверяет calendar_sk и route_sk IS NULL
с порогом.
- LOW: добавлен стабильный tie-breaker (ticket_no) при дедупликации
passengers.
- добавлена секция backfill/reprocess политики.
- Проверка:
- cat docs/internal/bookings_dds_design.md.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Зачем:
- зафиксировать архитектурные решения DDS до начала реализации (для Codex).
- Что:
- создан docs/internal/bookings_dds_design.md с полным планом DDS.
- 6 измерений (calendar, airports, airplanes, tariffs, passengers, routes) + факт flight_sales.
- dim_routes реализует классический SCD2 с hashdiff.
- все остальные измерения — SCD1 UPSERT со стабильными SK.
- факт — инкрементальный UPSERT по зерну (ticket_no, flight_id).
- Проверка:
- cat docs/internal/bookings_dds_design.md.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Зачем:
- подготовлена учебная реализация ODS слоя с типизацией, UPSERT и DQ, чтобы продолжить работу от STG к DDS/DM.
- Что:
- добавлены SQL-скрипты `sql/ods/*_ddl.sql`, `sql/ods/*_load.sql`, `sql/ods/*_dq.sql` для 9 сущностей bookings.
- добавлены DAG `bookings_ods_ddl` и `bookings_to_gp_ods`, а также smoke-тесты для новых графов.
- ODS DDL интегрирован в `sql/ddl_gp.sql`; документация и план обновлены под единый запуск через `make ddl-gp`.
- Проверка:
- `make test`.
- `make ddl-gp`.
- Зачем:
- codex нашёл баги, которые сломали бы первый прогон ODS.
- Что:
- resolve batch: MAX(batch_id) заменён на ORDER BY load_dttm DESC LIMIT 1
(run_id — строка, лексикографический MAX не гарантирует хронологию).
- ручная проверка: добавлен make ddl-gp-ods (без него ODS-объекты не создадутся).
- routes/flights FK: расширено пояснение, почему проверка по route_no без
validity допустима в ODS и что учитывать при join в DDS.
- Проверка:
- make test (11 passed, 4 skipped).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Зачем:
- v2 содержал баги (CTE scope, distribution key), неточности маппинга
колонок и пробелы в описании DAG-контракта, что сломало бы реализацию.
- Что:
- исправлен CTE scope: дублирование CTE в UPDATE и INSERT statements.
- ods.tickets: DISTRIBUTED BY (ticket_no) вместо book_ref для UPSERT.
- добавлен Python-сниппет resolve_stg_batch_id (PythonOperator + XCom).
- заменены {{ params.stg_batch_id }} → {{ ti.xcom_pull(...) }} во всех SQL.
- <> заменён на IS DISTINCT FROM (NULL-safe change detection).
- DISTINCT ON заменён на ROW_NUMBER() (стандартный DE-паттерн).
- добавлена секция 4.3 с полной таблицей маппинга STG → ODS.
- routes: scheduled_departure_time → departure_time, duration без rename.
- DAG-граф: resolve_stg_batch_id как корневой таск, параллельные ветки.
- DQ: добавлена проверка «батч не пустой» для snapshot-справочников.
- DoD: убрано valid_from/valid_to, оставлено _load_id/_load_ts/event_ts.
- Проверка:
- make test (11 passed, 4 skipped).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Зачем:
- нужен единый стандарт именования полей, чтобы новые слои не расходились с учебными материалами.
- Что:
- добавлен единый документ с правилами нейминга `docs/internal/naming_conventions.md`.
- полностью переписан `docs/internal/bookings_ods_design.md` в эталонный учебный план ODS (SCD1, батч-контракт, DQ, граф DAG).
- добавлены ссылки на стандарт нейминга в `docs/README.md`, `docs/internal/db_schema.md` и `AGENTS.md`.
- Проверка:
- проверен diff по измененным файлам (`git diff`).
- Зачем:
- зафиксировать архитектурное решение для ODS слоя перед началом разработки.
- Что:
- создан файл docs/internal/bookings_ods_design.md.
- описана архитектура ODS и отличия от STG слоя.
- добавлены схемы таблиц (справочники с SCD Type 2, транзакции с UPSERT).
- Проверка:
- git show --stat HEAD
- Зачем:
- исключены ложные падения DQ при пустом source в bookings-db.
- Что:
- в TESTING.md добавлены pre-check команды COUNT(*) перед Trigger DAG.
- в docs/agent-dag-testing.md добавлена обязательная проверка source и fallback при COUNT(*) = 0.
- в таблицу типичных проблем добавлен кейс падения check_airports_dq/check_airplanes_dq с ошибкой "..._ext нет строк".
- Проверка:
- rg -n "source непустой|COUNT\(\*\) = 0|bookings-generate-day|check_airports_dq" TESTING.md docs/agent-dag-testing.md
- Зачем:
- AI-агенты пытались тестировать DAG через браузер вместо CLI/API,
так как не было явных инструкций по программному подходу.
- Что:
- добавлен docs/agent-dag-testing.md: CLI, REST API Airflow,
проверка параллельности, запросы в Greenplum, E2E-тест, шпаргалка команд.
- в AGENTS.md добавлена ссылка на новый гайд в раздел «Тестирование».
- из docs/README.md убрана ссылка (файл для людей, не для агентов).
- Проверка:
- cat docs/agent-dag-testing.md && grep agent-dag-testing AGENTS.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Зачем:
- необходимо зафиксировать контекст и правила работы с проектом для Claude AI.
- Что:
- создан файл CLAUDE.md с описанием структуры проекта.
- добавлены инструкции по коммитам и стилю кода.
- Проверка:
- git show --stat HEAD
- Зачем:
- линейный граф маскировал реальные зависимости данных; для эталонного
стенда важно показать менти параллельный граф там, где данные независимы.
- Что:
- airports и airplanes грузятся параллельно после check_tickets_dq.
- routes ждёт обоих (DQ проверяет ссылочную целостность на оба справочника).
- seats зависит только от airplanes и работает параллельно с веткой
routes → flights → segments → boarding_passes.
- finish_summary ждёт обе ветки (check_boarding_passes_dq + check_seats_dq).
- datetime.utcnow() заменён на datetime.now(UTC) в csv_to_greenplum.py.
- smoke-тесты дополнены проверкой параллельности и второй ветки.
- документация обновлена с ASCII-схемой нового графа.
- Проверка:
- make test (11 passed, 4 skipped), make lint — чисто.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>