From 5f3e32c03120076a4b186fbad786da36ebb6ac7e Mon Sep 17 00:00:00 2001 From: Dmitry Dementev Date: Fri, 9 Jan 2026 18:48:18 +0300 Subject: [PATCH] =?UTF-8?q?=D0=93=D0=BB=D1=83=D0=B1=D0=BE=D0=BA=D0=B0?= =?UTF-8?q?=D1=8F=20=D0=BF=D0=B5=D1=80=D0=B5=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 2 +- README.md | 527 +++++---------------------- TESTING.md | 5 +- docs/README.md | 17 + docs/bookings_to_gp_stage.md | 100 +++++ docs/internal/bookings_stg_design.md | 4 +- docs/internal/bookings_stg_readme.md | 80 ---- docs/internal/pxf_bookings.md | 2 +- docs/stack.md | 125 +++++++ educational-tasks.md | 6 +- sql/ddl_gp.sql | 2 +- 11 files changed, 340 insertions(+), 530 deletions(-) create mode 100644 docs/README.md create mode 100644 docs/bookings_to_gp_stage.md delete mode 100644 docs/internal/bookings_stg_readme.md create mode 100644 docs/stack.md diff --git a/AGENTS.md b/AGENTS.md index 314f953..6562f98 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -66,7 +66,7 @@ ## Безопасность и конфигурация - Все настройки — через `.env`; креды в коде не хардкодим. Частые переменные: `GP_*`, `PG_*`, `AIRFLOW_*`, `CSV_*`. -- `make down` удаляет тома — предупреждайте студентов, что данные пропадут. +- `make clean` удаляет тома — предупреждайте студентов, что данные пропадут. ## Для агента (особенности аудитории) - Пишите простыми словами. Добавляйте короткие комментарии к нетривиальной логике. diff --git a/README.md b/README.md index a1334a8..276d364 100644 --- a/README.md +++ b/README.md @@ -1,493 +1,140 @@ -# airflow-dwh-gp-lab +# airflow-dwh-gp-lab -Учебный стенд: ETL из Postgres в Greenplum с оркестрацией в Airflow. +Учебный стенд для лабораторных по Data Engineering: **Airflow** оркестрирует загрузку данных из демо‑БД +**bookings** (Postgres) в **Greenplum**. -Добро пожаловать в учебный стенд для изучения основ Data Engineering! Этот проект поможет вам освоить ключевые инструменты современных data pipeline: **Airflow** для оркестрации, **pandas/CSV** для подготовки данных, **Postgres** с демобазой **bookings** как источник и **Greenplum** как аналитическую базу данных. +## Зачем этот стенд -Если вы проходите стенд как серию лабораторных, смотрите также файл с заданиями: `educational-tasks.md`. +Основная цель стенда — дать вам удобное место для лабораторных работ и будущей курсовой: +вы построите небольшое аналитическое хранилище данных (DWH) на базе **Greenplum** и закрепите навыки: -## 🎯 Что вы узнаете +- моделирования данных (слои DWH, модели, витрины); +- построения ETL/ELT; +- работы с Airflow и Greenplum. -- Как настроить локальный стек данных с помощью Docker -- Как Airflow управляет workflow и координирует задачи -- Как генерировать датасеты через pandas и сохранять их в CSV -- Как загружать данные в Greenplum пакетами и избегать дублей -- Как проверять качество данных в автоматизированных pipeline -- Основы проектирования ETL/ELT процессов - - Как работать с демо-БД bookings в Postgres как источником для будущего DWH +В курсовой у нас один источник данных — демо‑БД **bookings**. В стенде уже есть готовый учебный пример +загрузки **bookings → stg в Greenplum**, чтобы вы могли сфокусироваться на DWH‑части (ODS/DDS/DM) и +не тратить время на инфраструктуру. -## 👩‍🎓 Для студентов (10‑минутный чек‑лист) +## Что внутри -- Установите Docker Desktop и Git. -- Скопируйте настройки: `cp .env.example .env`. -- Поднимите стенд: `make up` (или `docker compose up -d` — сервис `airflow-init` запустится автоматически при первом старте). -- Откройте UI: http://localhost:8080 (admin/admin). -- Включите и запустите DAG `csv_to_greenplum`. Дождитесь Success. -- Проверьте данные: `make gp-psql` → `SELECT COUNT(*) FROM public.orders;`. -- Дополнительно: запустите `csv_to_greenplum_dq` — все проверки должны быть зелёные. +- **Airflow** (UI: http://localhost:8080, логин/пароль: admin/admin) +- **Greenplum** (single‑node для обучения; внешний порт по умолчанию `5435`) +- **bookings-db** (Postgres с демо‑БД `demo`; внешний порт по умолчанию `5434`) +- **PXF** как “транспорт” между Postgres и Greenplum (уже настроен в образе) +- Побочный пример: загрузка данных через **pandas/CSV** (`csv_to_greenplum`) -Если что‑то не работает — смотрите «Типичные проблемы» и «Быстрый reset» ниже. +## PXF (в 5 строк) -## 🚀 Быстрый старт (для новичков) +PXF (Platform Extension Framework) — компонент Greenplum для работы с внешними источниками. +В этом стенде PXF используется для чтения таблицы `bookings.bookings` из Postgres прямо из Greenplum +через внешнюю таблицу `stg.bookings_ext`. Поэтому загрузка в `stg.bookings` выглядит как обычный +`INSERT ... SELECT` без промежуточных CSV. +Подробное руководство по PXF смотрите в официальной документации Greenplum. -### Шаг 1: Подготовка окружения +## Быстрый старт (основной сценарий: bookings → stg) -**Требования:** -- Docker Desktop (Windows/Mac) или Docker Engine 24+ (Linux) -- Git для клонирования репозитория - -> 💡 **Совет:** Если у вас Windows, рекомендуем использовать WSL (Windows Subsystem for Linux) для лучшей совместимости. - -### Шаг 2: Настройка проекта +1) Скопируйте настройки: ```bash -# Скопируйте файл настроек cp .env.example .env - -# Запустите стек (это может занять 2-3 минуты при первом запуске) -docker compose up -d ``` -### Шаг 3: Первый запуск pipeline - -1. Откройте Airflow UI: **http://localhost:8080** (логин/пароль: admin/admin) -2. Найдите DAG с названием **csv_to_greenplum** -3. Нажмите на переключатель слева от названия DAG, чтобы включить его -4. Нажмите кнопку **Trigger** (значок воспроизведения ▶️) - -🎉 **Поздравляем!** Вы только что запустили свой первый data pipeline: -- Система сгенерировала 1000 тестовых заказов при помощи pandas -- Датасет сохранился в CSV-файл в каталоге `./data` -- Airflow загрузил данные из CSV в Greenplum без дублей по `order_id` - -### Шаг 4: Проверка результатов - -**Проверка вручную:** -```bash -# Подключитесь к Greenplum и проверьте данные -docker compose exec greenplum bash -c "su - gpadmin -c 'psql -p 5432 -d gp_dwh'" - -# Внутри psql выполните: -\dt # Показать таблицы -SELECT count(*) FROM public.orders; # Посчитать записи - -# Посмотреть несколько строк -SELECT * FROM public.orders LIMIT 5; -``` - -CSV-файлы после выполнения DAG остаются в директории `./data`. Их можно открыть любым редактором или изучить через pandas. - -### Быстрый reset - -Если после изменений что‑то «сломалось»: +2) Поднимите стенд: ```bash -make down # Остановить и удалить контейнеры/сети (volumes сохраняются) make up +# если make не установлен: docker compose up -d ``` -Если проблема связана с «грязной» остановкой и данными в томах (например, Greenplum не стартует), -используйте полный reset: `make clean && make up` (данные в Docker-томах будут потеряны). - ---- - -## 🛠️ Подробная настройка (для уверенных пользователей) - -> Если вы впервые запускаете стенд, этот раздел можно пролистать и вернуться к нему позже. - -### Установка Make (опционально) - -Для удобства работы с проектом рекомендуем установить `make`: - -- **Linux (Debian/Ubuntu):** `sudo apt install -y make` -- **macOS:** `brew install make` -- **Windows:** - - WSL: `sudo apt install -y make` - - Chocolatey: `choco install make` - - Scoop: `scoop install make` - -С `make` команды становятся короче: -```bash -make up # Запуск стека (включая airflow-init при первом старте) -make logs # Просмотр логов -make gp-psql # Подключение к Greenplum -``` - -### Настройка подключения к Greenplum в Airflow - -По умолчанию готовые DAG используют Airflow Connections. В docker-compose они -заводятся автоматически через переменные окружения: - -- `AIRFLOW_CONN_GREENPLUM_CONN` — подключение к Greenplum с `conn_id=greenplum_conn`; -- `AIRFLOW_CONN_BOOKINGS_DB` — подключение к демо-БД bookings с `conn_id=bookings_db`. - -Такие подключения подхватываются из окружения и могут не отображаться в UI, -но для DAG это нормально — `PostgresOperator` найдёт их по `conn_id`. - -При желании вы можете создать или отредактировать подключение вручную в UI: - -1. Airflow UI → **Admin → Connections → Add a new record** -2. Заполните поля: - - **Conn Id:** `greenplum_conn` - - **Conn Type:** `Postgres` - - **Host:** `greenplum` - - **Schema:** `gp_dwh` - - **Login:** `gpadmin` - - **Password:** `gpadmin` - - **Port:** `5432` - ---- - -### Greenplum + PXF: свой образ - -Чтобы избежать проблем с правами и нестабильных запусков, Greenplum собирается -из собственного `Dockerfile.greenplum`. В образ вшиты: - -- JDBC-драйвер PostgreSQL; -- конфигурация PXF-сервера `bookings-db`; -- ensure-скрипт, который при каждом старте контейнера докладывает файлы в `PXF_BASE`. - -Дополнительно при старте контейнера: - -- базовые конфиги PXF копируются в `PXF_BASE/conf` (если их ещё нет); -- создаются каталоги `PXF_BASE/run` и `PXF_BASE/logs`; -- `CREATE EXTENSION pxf` выполняется автоматически, когда Greenplum становится доступен (с ретраями). - -Healthcheck сервиса `greenplum` учитывает не только готовность Greenplum, но и запуск PXF, -а также наличие `extension pxf` — это нужно, чтобы Airflow не стартовал раньше PXF. - -Сборка и запуск: - -- `make build` — собрать образ (явно); -- `make up` — поднимет стек и соберёт образ, если он ещё не создан. - -Обновление PXF-конфигов: - -- изменили файлы в `pxf/` → выполните `make build` и перезапустите контейнер; -- для принудительной перезаписи файлов в `PXF_BASE` используйте `PXF_SEED_OVERWRITE=1`; -- для принудительного `pxf cluster sync` при старте используйте `PXF_SYNC_ON_START=1`. - -Проверка PXF: - -- статус: `docker compose exec greenplum bash -lc "su - gpadmin -c '/usr/local/pxf/bin/pxf cluster status'"`; -- логи: `greenplum_data:/data/pxf/logs` (внутри контейнера — `/data/pxf/logs`). - ---- - -### Airflow: свой образ - -Airflow тоже собирается из собственного `Dockerfile.airflow`, чтобы зависимости ставились при сборке, а не во время старта контейнеров. В образ включены: - -- Python‑зависимости из `airflow/requirements.txt`; -- утилита `psql` для быстрых проверок внутри контейнера. - -Если меняли `airflow/requirements.txt` или `Dockerfile.airflow`, пересоберите образы: `make build`, затем `make up`. - -В docker-compose по умолчанию задан `AIRFLOW__CORE__EXECUTOR=LocalExecutor` (параллельное выполнение задач). Если нужен последовательный режим — замените на `SequentialExecutor` в `docker-compose.yml`. - ---- - -### Локальное окружение разработчика - -Локальным окружением управляет [uv](https://docs.astral.sh/uv/) — он скачивает нужный Python и создаёт `.venv` на основе `pyproject.toml` / `uv.lock`. +3) Инициализируйте демо‑БД bookings: ```bash -uv sync +make bookings-init ``` -`uv sync` сам подтянет версию Python из `.python-version`/`pyproject.toml`, создаст `.venv` и установит зависимости. Для тех же действий можно использовать `make dev-sync`. Цель `make dev-setup` (или вручную `uv python install` + `uv python pin`) нужна только когда вы меняете версию Python или прогреваете кэш. +4) Подготовьте STG‑объекты в Greenplum (выберите один вариант): -> Если требуется «классическое» активированное окружение, после `uv sync` выполните `.\.venv\Scripts\Activate.ps1` в PowerShell или `source .venv/bin/activate` в Unix-терминале. +- Учебный вариант: в Airflow UI запустите DAG `bookings_stg_ddl`; +- Технический шорткат: `make ddl-gp` (применяет все DDL разом вручную). -Проверки и форматирование выполняем через uv: +5) Запустите основной DAG `bookings_to_gp_stage`. + +6) Проверьте результат в Greenplum: ```bash -make test # uv run pytest -q -make lint # black/isort в режиме проверки -make fmt # автоформатирование black + isort +make gp-psql +-- внутри psql: +SELECT COUNT(*) FROM stg.bookings; +SELECT * FROM stg.bookings ORDER BY src_created_at_ts DESC LIMIT 10; ``` -#### Быстрый старт с uv +Подробнее про логику DAG и проверки — `docs/bookings_to_gp_stage.md`. + +## DAG-и в стенде + +Основные (для потока bookings → DWH): + +- `bookings_stg_ddl` — создаёт `stg.bookings_ext` и `stg.bookings` в Greenplum; +- `bookings_to_gp_stage` — генерирует учебный день в `bookings-db` и грузит инкремент в `stg.bookings` + (через PXF), затем выполняет DQ‑проверку. + +Вспомогательные (побочный трек с CSV): + +- `orders_base_ddl` — создаёт таблицу `public.orders` для CSV‑пайплайна; +- `csv_to_greenplum` — pandas → CSV → Greenplum (пример загрузки без источника‑БД); +- `csv_to_greenplum_dq` — проверки качества данных для `public.orders`. + +## Полезные команды ```bash -uv sync -uv run pytest -q -uv run black --check airflow tests +make up # поднять стек +make logs # логи airflow-webserver и airflow-scheduler +make gp-psql # psql в Greenplum +make bookings-psql # psql в демо-БД bookings (Postgres) +make ddl-gp # применить DDL к Greenplum вручную (вместо DDL-DAG) +make down # остановить и удалить контейнеры/сети (volumes сохраняются) +make clean # полный reset: удалить контейнеры/сети и volumes (данные будут потеряны) ``` -> Не устанавливайте пакеты напрямую через `pip install --user ...`. Если что-то уже попало в user-site, удалите `pip uninstall ` и проверьте `pip list --user`. ---- +## Подключение через DBeaver (опционально) - -## 📋 Что входит в стенд - -### Основные компоненты -- **Greenplum** — аналитическая база данных для хранения и анализа данных -- **Airflow** — оркестратор workflow и задач -- **Postgres** — база метаданных для Airflow -- **Postgres (bookings)** — отдельная демо-БД bookings (источник данных для будущего DWH в Greenplum) -- **pandas** — библиотека для генерации и анализа данных в формате CSV - -### Готовые DAG (workflow) -- **orders_base_ddl** — создаёт базовую таблицу `public.orders` для CSV‑пайплайна -- **bookings_stg_ddl** — готовит схему `stg` и таблицы `stg.bookings_ext` / `stg.bookings` -- **csv_to_greenplum** — базовый pipeline: pandas → CSV → Greenplum -- **bookings_to_gp_stage** — пример загрузки из демо‑БД bookings в слой STG -- **csv_to_greenplum_dq** — проверки качества данных (наличие таблицы, схема, дубликаты) - -> Учебный путь — триггернуть DDL‑DAG: для CSV `orders_base_ddl`, для bookings `bookings_stg_ddl`. Технический шорткат для быстрой инициализации — `make ddl-gp` (он не вызывается автоматически при старте контейнеров). - -### Полезные команды -```bash -# Основные команды -make up # Запустить весь стенд (Airflow инициализируется автоматически при первом старте) -make stop # Остановить контейнеры, не трогая данные -make down # Остановить и удалить контейнеры/сети (volumes сохраняются) -make clean # Полный reset: остановить и удалить контейнеры/сети и тома (данные будут потеряны) -make airflow-init # Ручной запуск инициализации Airflow (обычно не нужен) -make ddl-gp # Применить DDL к Greenplum вручную -make gp-psql # Подключиться к Greenplum через psql -make bookings-init # Установить демобазу bookings в Postgres (по умолчанию генерирует 1 день) -make bookings-generate-day # Добавить ещё один день данных в bookings (можно вызвать несколько раз) -make bookings-psql # Подключиться к демобазе bookings (БД demo) - -# Проверка данных -make logs # Следить за логами Airflow - -# Логи задач Airflow сохраняются в Docker-томе `airflow_logs` -# и переживают `docker compose down`/`up` (удаляются при `docker compose down -v` / `make clean`). - -# Контроль генерации bookings -docker compose -f docker-compose.yml exec bookings-db bash -lc 'PGPASSWORD="$POSTGRES_PASSWORD" psql -U "$POSTGRES_USER" -d demo -c "SELECT busy();"' -# busy() = t — генерация ещё идёт; f — завершена. При необходимости можно вызвать CALL abort(); и запустить генерацию заново. -``` - -### Генерация следующего дня в bookings - -- При `make bookings-init` автоматически генерируется `BOOKINGS_INIT_DAYS` суток, начиная с даты `BOOKINGS_START_DATE` (по умолчанию один день с `2017-01-01`). -- Дальше каждый вызов `make bookings-generate-day` или генерации через DAG добавляет ровно **один** следующий день после `max(book_date)` в `bookings.bookings` — генератор сам смотрит последнюю дату. -- Рекомендуемый учебный сценарий для DAG `bookings_to_gp_stage`: запускать DAG по одному дню вперёд, выбирая в форме Trigger логическую дату `Execution Date (ds)`, совпадающую с тем днём, который вы хотите загрузить (например, `2017-01-01`, затем `2017-01-02` и т.д.). - -- Быстрее всего: `make bookings-generate-day` — читает GUC и сам вызывает `continue`. -- Вручную из psql/DBeaver (подзапросы в аргументах CALL не работают, поэтому через DO-блок): - ```sql - DO $$ - DECLARE - v_next_day timestamptz; - BEGIN - SELECT date_trunc('day', max(book_date)) + interval '1 day' - INTO v_next_day - FROM bookings.bookings; - CALL continue(v_next_day); -- или CALL continue(v_next_day, 4) для параллельности - END $$; - ``` -- Не вызывайте `CALL generate(...)` поверх существующих данных: она делает TRUNCATE и создаёт демобазу заново. - ---- - -## ⚙️ Настройка через переменные окружения - -Все настройки находятся в файле `.env`. Основные параметры: +Перед подключением убедитесь, что стенд поднят (`make up`). ### Greenplum -- `GP_USER` — пользователь (по умолчанию: gpadmin) -- `GP_PASSWORD` — пароль (по умолчанию: gpadmin) -- `GP_DB` — база данных (по умолчанию: gp_dwh) -- `GP_PORT` — порт Greenplum внутри Docker-сети (по умолчанию: 5432, менять обычно не нужно; внешний порт на хосте для подключения клиентов — 5435). -### Демо-БД bookings (Postgres) -- `BOOKINGS_DB_USER` — пользователь Postgres для демобазы (по умолчанию: bookings) -- `BOOKINGS_DB_PASSWORD` — пароль пользователя (по умолчанию: bookings) -- `BOOKINGS_DB_NAME` — база данных, из которой запускается установка генератора (по умолчанию: bookings) -- `BOOKINGS_DB_PORT` — внешний порт для подключения к контейнеру bookings-db (по умолчанию: 5434) -- `BOOKINGS_START_DATE` — начальная дата модельного времени (по умолчанию: 2017-01-01) -- `BOOKINGS_INIT_DAYS` — сколько дней сгенерировать при первой инициализации (по умолчанию: 1, чтобы увидеть данные без долгого ожидания; можно менять при вызове `BOOKINGS_INIT_DAYS=... make bookings-init`) -- `BOOKINGS_JOBS` — число параллельных джобов генератора bookings (по умолчанию: 1; при 1 генерация идёт синхронно без dblink) +- `Host`: `localhost` +- `Port`: `5435` +- `Database`: значение `GP_DB` из `.env` (по умолчанию `gp_dwh`) +- `Username`: значение `GP_USER` (по умолчанию `gpadmin`) +- `Password`: значение `GP_PASSWORD` (по умолчанию `gpadmin`) -### CSV pipeline -- `CSV_DIR` — путь к каталогу с CSV внутри контейнеров Airflow (по умолчанию: `/opt/airflow/data`) -- `CSV_ROWS` — количество строк, генерируемых DAG (по умолчанию: 1000) +### bookings-db (Postgres, демо-БД `demo`) -### Airflow -- `GP_CONN_ID` — ID подключения (по умолчанию: greenplum_conn) +- `Host`: `localhost` +- `Port`: значение `BOOKINGS_DB_PORT` из `.env` (по умолчанию `5434`) +- `Database`: `demo` +- `Username`: значение `BOOKINGS_DB_USER` (по умолчанию `bookings`) +- `Password`: значение `BOOKINGS_DB_PASSWORD` (по умолчанию `bookings`) ---- +## Документация -## 🔍 Продвинутые темы +- Учебные задания для менти: `educational-tasks.md` (в README задач нет намеренно). +- План тестирования/проверок и негативные кейсы: `TESTING.md`. +- Дополнительные заметки и технические детали: `docs/README.md`. -> Этот раздел не обязателен при первом прохождении стенда; к нему удобно вернуться, когда базовый CSV‑pipeline уже понятен. - -### Архитектура pipeline - -**Поток данных в DAG `csv_to_greenplum`:** -1. `create_orders_table` — создаёт таблицу `public.orders` в Greenplum -2. `generate_csv` — генерирует датасет при помощи pandas и сохраняет CSV в `CSV_DIR` -3. `preview_csv` — выводит предпросмотр и статистику по данным -4. `load_csv_to_greenplum` — загружает CSV во временную таблицу и переносит новые строки в `public.orders` - -> 💡 **Безопасность повторного запуска:** Pipeline защищен от дубликатов, поэтому его можно запускать многократно. - -### Проверка качества данных - -Запустите DAG `csv_to_greenplum_dq` для автоматической проверки: -- Наличие таблицы в базе -- Соответствие схемы ожидаемой структуре -- Объем загруженных данных -- Отсутствие дубликатов записей - -### Пример DAG с SQL-скриптами (bookings → stg) - -> Если вы ещё не дошли до части про bookings и слои DWH, этот подраздел можно пропустить на первом чтении. - -В репозитории есть учебный DAG `bookings_to_gp_stage`, который показывает «канонический» способ работы с SQL в Airflow: - -- подключение к БД через Airflow Connections (`bookings_db`, `greenplum_conn`); -- бизнес-логика инкрементальной загрузки и DQ вынесена в SQL-файлы в каталоге `sql/`: - - `sql/src/bookings_generate_day_if_missing.sql` — генерация следующего учебного дня в демо-БД bookings (или нескольких стартовых дней, если база пуста); - - `sql/stg/bookings_ddl.sql` — DDL для схемы `stg` и таблиц `stg.bookings_ext` / `stg.bookings`; - - `sql/stg/bookings_load.sql` — загрузка инкремента из `stg.bookings_ext` в `stg.bookings` на основе «хвоста» после предыдущих батчей; - - `sql/stg/bookings_dq.sql` — проверка количества строк между источником и stg за то же окно. - -Фрагмент DAG: - -```python -load_bookings_to_stg = PostgresOperator( - task_id="load_bookings_to_stg", - postgres_conn_id="greenplum_conn", - sql="stg/bookings_load.sql", - params={"batch_id": "{{ run_id }}"}, -) -``` - -Такой подход помогает держать оркестрацию (DAG) и SQL-логику в отдельных файлах и легче сравнивать её с теорией из статьи про моделирование DWH. - -### Ограничения учебного стенда - -- **Greenplum** запущен в single-node режиме (для обучения) -- В продакшене Greenplum обычно разворачивают кластером на нескольких серверах -- Используется Greenplum 6 (широко доступная версия), хотя Greenplum 7 предлагает больше возможностей - ---- - -## 🧩 Подключение к базам через DBeaver - -> Необязательный раздел: нужен только если вы хотите смотреть данные через DBeaver. Для базовых заданий достаточно `make gp-psql`. - -Ниже — краткая инструкция, как подключиться к Greenplum и демо-БД bookings из DBeaver. Перед этим убедитесь, что стенд запущен: - -- `cp .env.example .env` (если ещё не делали) -- `make up` -- `make bookings-init` -- `make ddl-gp` - -### Greenplum (аналитическая БД) - -1. Откройте DBeaver → **New Database Connection**. -2. Выберите драйвер **PostgreSQL** (или **Greenplum**, если он есть в вашей версии DBeaver). -3. На вкладке **Main** заполните поля (по умолчанию): - - `Host`: `localhost` - - `Port`: `5435` (внешний порт Greenplum на хосте) - - `Database`: значение `GP_DB` (по умолчанию `gp_dwh`) - - `Username`: значение `GP_USER` (по умолчанию `gpadmin`) - - `Password`: значение `GP_PASSWORD` (по умолчанию `gpadmin`) -4. Нажмите **Test Connection** → **OK**, затем **Finish**. - -После подключения: - -- Основные таблицы лаба — в схеме `public` базы `gp_dwh` (например, `public.orders`). -- После настройки PXF и выполнения `make ddl-gp` станет доступна внешняя таблица `public.ext_bookings_bookings` — чтение из демо-БД bookings через PXF. - -### bookings-db (демо-БД источника) - -Для работы с исходными данными (демо-БД `demo`) достаточно стандартного PostgreSQL-подключения. - -1. Откройте DBeaver → **New Database Connection** → драйвер **PostgreSQL**. -2. На вкладке **Main** укажите (значения по умолчанию из `.env.example`): - - `Host`: `localhost` - - `Port`: значение `BOOKINGS_DB_PORT` из `.env` (по умолчанию `5434`) - - `Database`: `demo` - - `Username`: `BOOKINGS_DB_USER` (по умолчанию `bookings`) - - `Password`: `BOOKINGS_DB_PASSWORD` (по умолчанию `bookings`) -3. Нажмите **Test Connection** → **OK**, затем **Finish**. - -После подключения: - -- Основные таблицы находятся в схеме `bookings` базы `demo` (например, `bookings.bookings`, `bookings.tickets`, `bookings.flights` и т.д.). -- Можно сравнивать данные: - - между `bookings.bookings` в Postgres и `public.ext_bookings_bookings` в Greenplum; - - между временем (`book_date`) в UTC в `demo` и локальным временем в Greenplum (учитывая `TZ=Europe/Moscow`). - -> Если вы меняли порты или креды в `.env`, не забудьте подставить те же значения в настройках соединений в DBeaver. - ---- - -## 🆘 Типичные проблемы и решения +## Типичные проблемы и решения | Проблема | Решение | |----------|---------| | Airflow UI не открывается | Дождитесь сообщения `Listening at: http://0.0.0.0:8080` в логах (`make logs`) | -| `database "demo" does not exist` в bookings‑DAG | Вы сделали полный reset с удалением томов (`docker compose down -v` / `make clean`), поэтому демобаза bookings не установлена. Запустите `make bookings-init` и повторите DAG. | -| Ошибка подключения к Greenplum | Убедитесь, что контейнер `greenplum` стал статусом `healthy` (проверьте `docker compose ps`) | -| Не открывается порт 8080/5433/5434/5435 | Проверьте, что эти порты не заняты локальными сервисами; при необходимости остановите их или измените порты в `.env`/`docker-compose.yml` | -| Нет файла в `./data` после запуска DAG | Проверьте логи задачи `generate_csv`, убедитесь, что `CSV_DIR` смонтирован в docker-compose | -| Команда `make` не найдена | Используйте полные команды `docker compose` или установите make | -| Greenplum не стартует/падает при старте | Попробуйте `make down && make up`. Если не помогло — полный reset: `make clean && make up` (удалит тома). | +| `database "demo" does not exist` в bookings‑DAG | Вы сделали reset с удалением volumes (`make clean` / `docker compose down -v`). Запустите `make bookings-init` и повторите DAG. | +| Ошибка подключения к Greenplum | Убедитесь, что контейнер `greenplum` имеет статус `healthy` (`docker compose ps`) | | `protocol "pxf" does not exist` | Перезапустите `greenplum` и повторите `bookings_stg_ddl`/`make ddl-gp` — расширение `pxf` создаётся автоматически при старте контейнера. | -| PXF не отвечает (Connection refused к порту 5888) | Проверьте `pxf cluster status` в контейнере `greenplum` и перезапустите сервис `greenplum`. | -| PXF не подхватывает изменения конфигов | Пересоберите образ (`make build`) и перезапустите `greenplum`. Для принудительной перезаписи файлов задайте `PXF_SEED_OVERWRITE=1`. | -| DAG `bookings_to_gp_stage` падает на внешней таблице/подключении к bookings | Убедитесь, что запущен контейнер `bookings-db` (`docker compose ps`, при необходимости `docker compose start bookings-db`), и выполнены `make bookings-init` и `make ddl-gp` или DAG `bookings_stg_ddl` | -| DAG `bookings_to_gp_stage` ругается на отсутствующие таблицы stg | Запустите DAG `bookings_stg_ddl` (или выполните `make ddl-gp`), затем повторите запуск | -| DAG не видит Greenplum/DEMObase по Airflow Connections | Убедитесь, что контейнеры `greenplum` и `bookings-db` запущены (`docker compose ps`). Подключения `greenplum_conn` и `bookings_db` задаются через переменные окружения `AIRFLOW_CONN_...` и могут не отображаться в UI, но `PostgresOperator` всё равно найдёт их по `conn_id`. При необходимости вы можете создать/отредактировать их вручную в разделе Connections. | - ---- - -## 📁 Структура проекта - -``` -├── docker-compose.yml # Описание всех сервисов -├── Dockerfile.airflow # Образ Airflow с зависимостями -├── Dockerfile.greenplum # Образ Greenplum с интегрированным PXF -├── .env.example # Шаблон настроек -├── Makefile # Удобные команды для работы -├── README.md # Обзор стенда -├── TESTING.md # Пошаговый план проверки -├── educational-tasks.md # Учебные задания для менти -├── airflow/ -│ └── dags/ # Файлы workflow (DAG) -│ ├── csv_to_greenplum.py -│ ├── csv_to_greenplum_dq.py -│ └── bookings_to_gp_stage.py -├── bookings/ # Скрипты и файлы для демобазы bookings в Postgres -├── sql/ -│ └── ddl_gp.sql # Общий DDL для Greenplum (подключает stg/src-скрипты) -├── docs/ # Дополнительные документы (архитектура, bookings/STG, PXF) -├── tests/ # Автоматические тесты (pytest) -└── pxf/ # Конфигурация и файлы для PXF -``` - ---- - -## 💡 Советы для дальнейшего обучения - -1. **Поэкспериментируйте с DAG** — измените параметры генерации данных или размер батча -2. **Добавьте свои проверки** — расширьте DAG `csv_to_greenplum_dq.py` -3. **Попробуйте другие источники** — замените генератор данных на чтение из файла или API -4. **Изучите Airflow deeper** — добавьте зависимости между задачами, настройте расписания - ---- - -## ✅ Тестирование - -- Локальные проверки: `make test` (pytest). Для форматирования — `make fmt`, для проверки — `make lint`. -- Пошаговый сценарий с Docker (включая негативные кейсы и reset) — см. `TESTING.md`. -- Полный smoke-тест стенда (сносит volumes!): `make e2e-smoke` — поднимает стек с нуля, прогоняет `csv_to_greenplum` и `bookings_to_gp_stage` через `airflow dags test` и проверяет, что в `public.orders` и `stg.bookings` появились строки. - - ---- +| DAG `bookings_to_gp_stage` ругается на отсутствующие таблицы stg | Запустите `bookings_stg_ddl` (или выполните `make ddl-gp`), затем повторите запуск | +| Порты 8080/5434/5435 заняты | Остановите локальные сервисы или измените порты в `.env`/`docker-compose.yml` | ## Благодарности -- **Postgres Pro** — за демо-БД bookings и генератор данных `demodb`: https://github.com/postgrespro/demodb (лицензия MIT: https://github.com/postgrespro/demodb/blob/main/LICENSE). +- **Postgres Pro** — за демо‑БД bookings и генератор данных `demodb`: https://github.com/postgrespro/demodb (лицензия MIT: https://github.com/postgrespro/demodb/blob/main/LICENSE). - **woblerr** — за Docker-сборку Greenplum: https://github.com/woblerr/docker-greenplum (образ: `woblerr/greenplum`, лицензия MIT: https://github.com/woblerr/docker-greenplum/blob/master/LICENSE). - -Удачи в изучении Data Engineering! 🚀 diff --git a/TESTING.md b/TESTING.md index 23437d6..35fd5a3 100644 --- a/TESTING.md +++ b/TESTING.md @@ -80,8 +80,9 @@ - Хостовые CSV: каталог `data/` (можно открыть любой файл и убедиться в структуре). ## 9. Завершение работы -- `make down` — выключает сервисы и удаляет тома (перезапишет данные в Greenplum!). -- При необходимости сохранить данные: скопировать CSV из `data/` и дампы из контейнера до `make down`. +- `make down` — выключает сервисы и удаляет контейнеры/сети (volumes сохраняются). +- Полный сброс данных (удаляет volumes): `make clean`. +- При необходимости сохранить данные: скопировать CSV из `data/` и сделать дампы до `make clean`. ## Текущий статус (пример успешного прогона) - `uv run pytest -q` — 11 passed, 2 smoke-теста DAG пропущены (Airflow не установлен в venv). diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..132330a --- /dev/null +++ b/docs/README.md @@ -0,0 +1,17 @@ +# Документация + +Этот каталог содержит дополнительные материалы к учебному стенду. + +## Быстрый путь (для менти) + +- [Быстрый старт и команды](../README.md) +- [Учебные задания](../educational-tasks.md) +- [План тестирования и проверки](../TESTING.md) +- [Главный учебный DAG: bookings → stg](bookings_to_gp_stage.md) + +## Технические детали (опционально) + +- [Как устроен Docker-стенд (образы, Connections, переменные окружения)](stack.md) +- [PXF в этом проекте (проектная реализация)](internal/pxf_bookings.md) +- [Дизайн stg для bookings (черновик)](internal/bookings_stg_design.md) +- [Про время/UTC в bookings (черновик)](internal/bookings_tz.md) diff --git a/docs/bookings_to_gp_stage.md b/docs/bookings_to_gp_stage.md new file mode 100644 index 0000000..a37bf59 --- /dev/null +++ b/docs/bookings_to_gp_stage.md @@ -0,0 +1,100 @@ +# DAG `bookings_to_gp_stage`: `bookings-db` → `stg` в Greenplum + +Этот DAG — основной учебный пример в стенде. Он показывает путь данных из источника **Postgres** +(`bookings-db`, демо‑БД `demo`) в сырой слой **STG** в **Greenplum** с инкрементальной загрузкой +и простой проверкой качества данных. + +## Что делает DAG + +- В источнике (`bookings-db`) генерирует следующий учебный день данных в `bookings.bookings` + (генератор всегда “шагает” вперёд от `max(book_date)`). +- В Greenplum загружает инкремент в `stg.bookings` через внешнюю таблицу `stg.bookings_ext` (PXF). +- Сверяет количество строк между источником (за окно инкремента) и загруженным батчем. + +## Что должно быть готово перед запуском + +1) Стек поднят: + +```bash +make up +``` + +2) Демо‑БД bookings установлена и содержит данные: + +```bash +make bookings-init +``` + +3) В Greenplum созданы `stg.bookings_ext` и `stg.bookings` (выберите один вариант): + +- учебный вариант: запустить DAG `bookings_stg_ddl` в Airflow UI; +- технический шорткат: `make ddl-gp`. + +4) Airflow Connections: + +- `bookings_db` — подключение к источнику `bookings-db`; +- `greenplum_conn` — подключение к Greenplum. + +По умолчанию они задаются через переменные окружения `AIRFLOW_CONN_...` в `docker-compose.yml`, +поэтому могут не отображаться в UI — для `PostgresOperator` это нормально. + +## Как запустить + +1) Откройте Airflow UI: http://localhost:8080 (admin/admin). +2) Запустите DAG `bookings_to_gp_stage` вручную (Trigger DAG). +3) Дождитесь статуса Success у всех задач. + +## Как это работает внутри (по шагам) + +1) `generate_bookings_day` + +- выполняет `sql/src/bookings_generate_day_if_missing.sql` в `bookings-db`; +- если `bookings.bookings` пустая — вызывает `generate(...)` на `BOOKINGS_INIT_DAYS`; +- иначе — вызывает `continue(...)`, добавляя ровно один следующий день. + +2) `load_bookings_to_stg` + +- выполняет `sql/stg/bookings_load.sql` в Greenplum; +- берёт строки из `stg.bookings_ext`, которые попадают в новое окно инкремента; +- вставляет их в `stg.bookings`, добавляя тех.колонки: + - `src_created_at_ts` (опорная метка времени для инкремента), + - `load_dttm`, + - `batch_id={{ run_id }}`. + +3) `check_row_counts` + +- выполняет `sql/stg/bookings_dq.sql` в Greenplum; +- считает количество строк в источнике за то же окно инкремента и сравнивает с количеством строк, + вставленных в `stg.bookings` для текущего `batch_id`; +- при расхождении делает `RAISE EXCEPTION` с понятным текстом. + +4) `finish_summary` + +- логирует краткую сводку в конце запуска. + +## Как проверить результат + +```bash +make gp-psql +``` + +Примеры запросов: + +```sql +SELECT COUNT(*) FROM stg.bookings; + +SELECT + src_created_at_ts, + load_dttm, + batch_id +FROM stg.bookings +ORDER BY src_created_at_ts DESC +LIMIT 10; +``` + +## Типичные ошибки + +- `database "demo" does not exist`: демо‑БД не установлена → выполните `make bookings-init`. +- Ошибки про `stg.bookings_ext`/`stg.bookings`: не применён DDL → запустите `bookings_stg_ddl` или `make ddl-gp`. +- Ошибки PXF (`protocol "pxf" does not exist`, connection refused): перезапустите `greenplum` и повторите DDL. + Для технических деталей см. `docs/internal/pxf_bookings.md`. diff --git a/docs/internal/bookings_stg_design.md b/docs/internal/bookings_stg_design.md index cc928e4..520182a 100644 --- a/docs/internal/bookings_stg_design.md +++ b/docs/internal/bookings_stg_design.md @@ -68,7 +68,7 @@ DDL будет добавлен в `sql/ddl_gp.sql` в блоке DDL для Gre - считаем режим `full` — загружаем все строки из `stg.bookings_ext`. - При последующих запусках: - читаем `max(src_created_at_ts)` из `stg.bookings` за все предыдущие загрузки; - - считаем, что нужно загрузить только строки, где `src_created_at_ts` больше этой максимальной метки и не позже конца текущего учебного дня. + - загружаем строки, где `src_created_at_ts` больше этой максимальной метки (верхняя граница по времени не задаётся). Таким образом, вся логика инкремента «замкнута» на один техно‑столбец `src_created_at_ts`, который студент потом сможет использовать и на следующих слоях (например, в CDC‑логике). @@ -88,7 +88,7 @@ DDL будет добавлен в `sql/ddl_gp.sql` в блоке DDL для Gre - `dag_id`: `bookings_to_gp_stage`. - Основные параметры: - - `batch_id` (по умолчанию `{{ ds_nodash }}`) — метка батча, которая попадает в `stg.bookings.batch_id`; + - `batch_id` (в текущей реализации `{{ run_id }}`) — метка батча, которая попадает в `stg.bookings.batch_id`; - подключения: - `bookings_db_conn_id` — Airflow connection к `bookings-db` (в коде DAG — `BOOKINGS_CONN_ID = "bookings_db"`); - `greenplum_conn_id` — Airflow connection к Greenplum (`GREENPLUM_CONN_ID = "greenplum_conn"`). diff --git a/docs/internal/bookings_stg_readme.md b/docs/internal/bookings_stg_readme.md deleted file mode 100644 index d544c09..0000000 --- a/docs/internal/bookings_stg_readme.md +++ /dev/null @@ -1,80 +0,0 @@ -# Мини‑README по учебному DAG bookings_to_gp_stage (черновик) - -_Внутренний файл, чтобы не забыть договорённости. Перед итоговой сдачей документацию по блоку bookings/STG нужно будет аккуратно собрать и переписать._ - -## 1. Что делает DAG - -- DAG `bookings_to_gp_stage` показывает учебный поток: - - источник: демо‑БД `bookings-db` (Postgres, схема `bookings`, таблица `bookings.bookings`); - - при каждом запуске генерируется один учебный день данных (идемпотентно); - - данные из `bookings.bookings` переливаются в сырой слой `stg.bookings` в Greenplum через PXF‑внешнюю таблицу `stg.bookings_ext`. -- Слой `stg` задуман как «сырой»: - - все бизнес‑колонки (`book_ref`, `book_date`, `total_amount`) хранятся как `TEXT`; - - есть тех.колонки `src_created_at_ts`, `load_dttm`, `batch_id`. - -Подробный дизайн описан в `docs/internal/bookings_stg_design.md`. - -## 2. Что нужно, чтобы DAG завёлся - -Минимальные предпосылки: - -- Стенд поднят: `make up`. -- Демо‑БД bookings инициализирована: `make bookings-init`. -- В Greenplum применён DDL (созданы схема `stg` и таблицы `stg.bookings_ext` / `stg.bookings`): - - учебный вариант: запустить DAG `bookings_stg_ddl` (он использует `sql/stg/bookings_ddl.sql`); - - технический шорткат: `make ddl-gp` применяет все DDL разом вручную. Команда сама не вызывается при старте контейнеров, её нужно запустить явно. -- В Airflow есть коннекты: - - `greenplum_conn` — к Greenplum; - - `bookings_db` — к сервису `bookings-db`. - По умолчанию они задаются через переменные окружения `AIRFLOW_CONN_...` в docker-compose, - поэтому могут не отображаться в UI, но `PostgresOperator` найдёт их по `conn_id`. При желании - их можно создать/отредактировать вручную через Admin → Connections. - -## 3. Последовательность задач в DAG - -- `generate_bookings_day`: - - PostgresOperator к `bookings-db`; - - выполняет SQL `/sql/src/bookings_generate_day_if_missing.sql`; - - скрипт смотрит на `max(book_date)` в `bookings.bookings`: - - если база пустая — берёт стартовую дату из GUC и генерирует `bookings.init_days` суток; - - если данные уже есть — добавляет один следующий учебный день после `max(book_date)` и пишет NOTICE с интервалом генерации. -- `load_bookings_to_stg`: - - PostgresOperator к Greenplum; - - выполняет SQL `/sql/stg/bookings_load.sql`; - - считает «старый» максимум `src_created_at_ts` (по предыдущим батчам) и грузит только новые строки из `stg.bookings_ext`, заполняя `src_created_at_ts`, `load_dttm`, `batch_id={{ ds_nodash }}`. -- `check_row_counts`: - - PostgresOperator к Greenplum; - - выполняет SQL `/sql/stg/bookings_dq.sql`; - - за то же окно инкремента считает количество строк в источнике и в `stg.bookings` (по текущему `batch_id`); - - при расхождении делает `RAISE EXCEPTION` с понятным текстом ошибки. -- `finish_summary`: - - логирует итог выполнения DAG за одно срабатывание. - -## 4. Как этим пользоваться студенту (черновой сценарий) - -1. Поднять стенд и подготовить источники: - - `make up` (Airflow инициализируется автоматически при первом старте) - - `make bookings-init` - - `make ddl-gp` -2. Открыть Airflow UI (`http://localhost:8080`) и включить DAG `bookings_to_gp_stage`. -3. Вызвать `Trigger` DAG (дату логического запуска можно оставить по умолчанию — она используется только как метка `batch_id`). -4. Посмотреть: - - в `bookings-db` ― что появился день с бронированиями; - - в Greenplum (`make gp-psql`) — данные в `stg.bookings`: - - `SELECT * FROM stg.bookings LIMIT 10;` - - `SELECT src_created_at_ts, load_dttm, batch_id FROM stg.bookings ORDER BY src_created_at_ts DESC LIMIT 10;` -5. Перезапустить DAG ещё несколько раз и увидеть, что: - - генерация в `bookings.bookings` идёт по одному дню вперёд от текущего `max(book_date)`; - - в `stg.bookings` появляются только новые записи (delta), помеченные разными `batch_id`. - -## 5. Примечания «на потом» - -- Текущая документация по блоку bookings/STG разбросана: - - `README.md` (общий обзор стенда), - - `docs/internal/bookings_tz.md` (источник bookings), - - `docs/internal/pxf_bookings.md` (PXF), - - `docs/internal/bookings_stg_design.md` (дизайн STG), - - этот файл (мини‑README по DAG). -- В будущем всё это нужно будет собрать в одну понятную историю для студента: - - отдельный раздел «Учебный пример: bookings → stg → dwh»; - - скриншоты DAG, примеры запросов и типичные ошибки. diff --git a/docs/internal/pxf_bookings.md b/docs/internal/pxf_bookings.md index 2c0d81f..b26f510 100644 --- a/docs/internal/pxf_bookings.md +++ b/docs/internal/pxf_bookings.md @@ -143,7 +143,7 @@ - `docker-compose.yml` (сервис `greenplum`: `build`, `hostname`, env, healthcheck) - `pxf/init/10_pxf_bookings.sh` (ensure‑логика) - `pxf/init/start_greenplum_with_pxf.sh` (старт контейнера) -- `README.md` (раздел «Greenplum + PXF: свой образ») +- `docs/stack.md` (раздел «Greenplum + PXF: свой образ») ## 10. Известная проблема: после `docker compose stop/start` Greenplum может упасть (auth для PXF) diff --git a/docs/stack.md b/docs/stack.md new file mode 100644 index 0000000..cc00c53 --- /dev/null +++ b/docs/stack.md @@ -0,0 +1,125 @@ +# Технические детали стенда (Docker / Airflow / Greenplum) + +Этот документ не обязателен для прохождения лабораторных, но полезен, если вы: + +- хотите понять, как устроен стенд “под капотом”; +- меняете конфиги/зависимости и пересобираете образы; +- отлаживаете проблемы со стартом Greenplum/PXF или Connections в Airflow. + +## Make (опционально, но удобно) + +Если `make` не установлен, можно пользоваться `docker compose ...`. +Но с `make` команды короче и проще. + +Установка `make` (если нужно): + +- Linux (Debian/Ubuntu): `sudo apt install -y make` +- macOS: `brew install make` +- Windows: + - WSL: `sudo apt install -y make` + - Chocolatey: `choco install make` + - Scoop: `scoop install make` + +Примеры: + +```bash +make up +make logs +make gp-psql +``` + +## Airflow Connections + +Готовые DAG по умолчанию подключаются к БД через Airflow Connections: + +- `greenplum_conn` — Greenplum; +- `bookings_db` — демо‑БД bookings (`bookings-db`). + +В `docker-compose.yml` Connections задаются через переменные окружения `AIRFLOW_CONN_...`, +поэтому они могут не отображаться в UI — для DAG это нормально. + +Если нужно завести вручную: + +1) Airflow UI → Admin → Connections → Add a new record +2) Пример для Greenplum: + - Conn Id: `greenplum_conn` + - Conn Type: `Postgres` + - Host: `greenplum` + - Schema: `gp_dwh` + - Login/Password: `gpadmin` / `gpadmin` + - Port: `5432` + +## Greenplum + PXF: свой образ + +Greenplum собирается из собственного `Dockerfile.greenplum`, чтобы: + +- не ловить проблемы с правами/`chown` при bind‑mount конфигов; +- держать PXF‑конфиги и JDBC‑драйвер внутри образа; +- делать старт контейнера идемпотентным. + +При старте контейнера: + +- seed‑конфиги PXF докладываются в `PXF_BASE` на persistent volume; +- создаются каталоги `PXF_BASE/run` и `PXF_BASE/logs`; +- расширение `pxf` создаётся автоматически, когда Greenplum становится доступен (с ретраями). + +Полезные команды: + +```bash +make build # пересобрать образы +docker compose ps # проверить health +``` + +Перезапись seed‑файлов в `PXF_BASE`: + +- `PXF_SEED_OVERWRITE=1` — перезаписать конфиги при старте; +- `PXF_SYNC_ON_START=1` — выполнить `pxf cluster sync` при старте. + +Подробнее: `docs/internal/pxf_bookings.md`. + +## Airflow: свой образ + +Airflow тоже собирается из собственного `Dockerfile.airflow`, чтобы зависимости ставились при сборке, +а не во время старта контейнеров. + +Если меняли `airflow/requirements.txt` или `Dockerfile.airflow`, пересоберите образы: + +```bash +make build +make up +``` + +## Локальное окружение разработчика (uv) + +Локальным окружением управляет `uv` — он создаёт `.venv` из `pyproject.toml` / `uv.lock`. + +```bash +uv sync +make test +make lint +make fmt +``` + +Не устанавливайте зависимости через `pip install --user ...` — это часто ломает окружение и IDE. + +## Переменные окружения (`.env`) + +Все настройки лежат в `.env` (шаблон: `.env.example`). + +### Greenplum + +- `GP_USER`, `GP_PASSWORD`, `GP_DB` +- `GP_PORT` — внутренний порт в Docker-сети (обычно `5432`), внешний порт на хосте фиксирован на `5435` + +### bookings-db (Postgres) + +- `BOOKINGS_DB_USER`, `BOOKINGS_DB_PASSWORD` +- `BOOKINGS_DB_PORT` — внешний порт (по умолчанию `5434`) +- `BOOKINGS_START_DATE` — стартовая дата модельного времени +- `BOOKINGS_INIT_DAYS` — сколько дней генерировать при первом `make bookings-init` +- `BOOKINGS_JOBS` — число джобов генератора (по умолчанию `1`) + +### CSV pipeline (побочный пример) + +- `CSV_DIR` — путь к каталогу с CSV внутри контейнеров Airflow (по умолчанию `/opt/airflow/data`) +- `CSV_ROWS` — количество строк, генерируемых DAG (по умолчанию `1000`) diff --git a/educational-tasks.md b/educational-tasks.md index 0ce7e3d..6d1bd48 100644 --- a/educational-tasks.md +++ b/educational-tasks.md @@ -72,7 +72,7 @@ ### 2.2. Знакомство с STG в Greenplum -1. Прочитайте `sql/stg/bookings_ddl.sql` и мини‑README `docs/internal/bookings_stg_readme.md` (если интересно — `docs/internal/bookings_stg_design.md`). +1. Прочитайте `sql/stg/bookings_ddl.sql` и краткое описание потока `docs/bookings_to_gp_stage.md` (если интересно — `docs/internal/bookings_stg_design.md`). 2. Ответьте себе на вопросы: - чем внешняя таблица `stg.bookings_ext` отличается от внутренней `stg.bookings`; - зачем нужны тех.колонки `src_created_at_ts`, `load_dttm`, `batch_id`; @@ -111,12 +111,12 @@ - `sql/src/bookings_generate_day_if_missing.sql` - `sql/stg/bookings_load.sql` - `sql/stg/bookings_dq.sql` -3. Соотнесите шаги DAG с документом `docs/internal/bookings_stg_readme.md`: +3. Соотнесите шаги DAG с документом `docs/bookings_to_gp_stage.md`: - генерация учебного дня в `bookings.bookings`; - загрузка инкремента в `stg.bookings`; - проверка количества строк между источником и STG. 4. Обратите внимание, как в DAG используется логическая дата запуска: - - `{{ ds_nodash }}` используется как `batch_id` — метка загрузки в таблице `stg.bookings` для конкретного запуска; + - `{{ run_id }}` используется как `batch_id` — метка загрузки в таблице `stg.bookings` для конкретного запуска; - сами даты данных (какие дни есть в `bookings.bookings`) определяются генератором по `max(book_date)`, а не по `ds`. На этом этапе достаточно понять общую цепочку. Детальные задания по переработке модели данных и построению ODS/DDS/DM слоёв будут добавлены позже. diff --git a/sql/ddl_gp.sql b/sql/ddl_gp.sql index ae63093..0e81d60 100644 --- a/sql/ddl_gp.sql +++ b/sql/ddl_gp.sql @@ -6,7 +6,7 @@ -- Чтобы не ломать задания, новые объекты лучше добавлять в отдельные файлы -- и подключать их отсюда, а существующие определения не удалять. -- --- Подробнее про STG/bookings: см. docs/internal/bookings_stg_readme.md. +-- Подробнее про STG/bookings: см. docs/bookings_to_gp_stage.md. -- Таблица для CSV‑пайплайна (csv_to_greenplum). \i base/orders_ddl.sql