From c95dab6478d84db14f02ca88e31e0893d59b06cd Mon Sep 17 00:00:00 2001 From: Dmitry Dementev Date: Mon, 8 Dec 2025 18:26:10 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D0=BA=D0=B8=20=D0=BF=D0=BE=20=D0=B3=D0=B5=D0=BD=D0=B5=D1=80?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D0=B8=20=D0=91=D0=94=20-=20=D0=B2=20=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D1=86=D0=B5=D1=81=D1=81=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 2 ++ .gitignore | 1 + Makefile | 25 +++++++++++++++++++++++-- README.md | 3 ++- bookings/generate_next_day.sql | 20 ++++++++++++++------ docs/internal/bookings_tz.md | 17 +++++++++++++++++ 6 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 docs/internal/bookings_tz.md diff --git a/.env.example b/.env.example index aafba2c..427970c 100644 --- a/.env.example +++ b/.env.example @@ -15,6 +15,8 @@ BOOKINGS_DB_NAME=bookings BOOKINGS_DB_PORT=5434 # Начальная дата модельного времени для генерации демобазы BOOKINGS_START_DATE=2017-01-01 +# Количество параллельных джобов генератора (по умолчанию 1) +BOOKINGS_JOBS=1 # Greenplum Configuration GP_USER=gpadmin diff --git a/.gitignore b/.gitignore index b34bbb2..f788724 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ __pycache__/ *.pyc .venv/ data/ +bookings/demodb/ diff --git a/Makefile b/Makefile index d0d9543..bed8b0b 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,9 @@ SHELL := /bin/bash UV := uv PYTHON_VERSION := 3.11 +DEMODB_REPO := https://github.com/postgrespro/demodb.git +DEMODB_COMMIT := d68de192850237719f09b47688d5f3fc94653ca6 +BOOKINGS_JOBS ?= 1 .PHONY: up down airflow-init logs gp-psql ddl-gp \ bookings-clone-demodb bookings-init bookings-psql bookings-generate-day \ @@ -26,18 +29,36 @@ ddl-gp: bookings-clone-demodb: mkdir -p bookings - test -d bookings/demodb || git clone --depth 1 https://github.com/postgrespro/demodb.git bookings/demodb + if [ ! -d bookings/demodb ]; then \ + git clone --depth 1 $(DEMODB_REPO) bookings/demodb; \ + git -C bookings/demodb fetch --depth 1 origin $(DEMODB_COMMIT); \ + git -C bookings/demodb checkout $(DEMODB_COMMIT); \ + fi bookings-init: bookings-clone-demodb docker compose -f docker-compose.yml up -d bookings-db docker compose -f docker-compose.yml exec bookings-db bash -lc 'cd /bookings/demodb && PGPASSWORD="$$POSTGRES_PASSWORD" psql -v ON_ERROR_STOP=1 -U "$$POSTGRES_USER" -d "$$POSTGRES_DB" -f install.sql' + docker compose -f docker-compose.yml exec bookings-db bash -lc '\ + CONNSTR="dbname=demo user=$$POSTGRES_USER password=$$POSTGRES_PASSWORD"; \ + PGPASSWORD="$$POSTGRES_PASSWORD" psql -v ON_ERROR_STOP=1 -U "$$POSTGRES_USER" -d "$$POSTGRES_DB" -c "ALTER DATABASE demo SET gen.connstr='\''$$CONNSTR'\'';" \ + ' + # Генерируем первый день данных, чтобы база не оставалась пустой + docker compose -f docker-compose.yml exec -T bookings-db bash -lc 'PGPASSWORD="$$POSTGRES_PASSWORD" psql -v ON_ERROR_STOP=1 -U "$$POSTGRES_USER" -d demo -v start_date="$${BOOKINGS_START_DATE:-2017-01-01}" -v jobs="$(BOOKINGS_JOBS)" <<'"'"'SQL'"'"' + SET bookings.start_date = :'start_date'; + \i /bookings/generate_next_day.sql + RESET bookings.start_date; + SQL' bookings-psql: docker compose -f docker-compose.yml exec bookings-db bash -lc 'PGPASSWORD="$$POSTGRES_PASSWORD" psql -U "$$POSTGRES_USER" -d demo' bookings-generate-day: docker compose -f docker-compose.yml up -d bookings-db - docker compose -f docker-compose.yml exec bookings-db bash -lc 'PGPASSWORD="$$POSTGRES_PASSWORD" psql -v ON_ERROR_STOP=1 -U "$$POSTGRES_USER" -d demo -v start_date="$${BOOKINGS_START_DATE:-2017-01-01}" -f /bookings/generate_next_day.sql' + docker compose -f docker-compose.yml exec -T bookings-db bash -lc 'PGPASSWORD="$$POSTGRES_PASSWORD" psql -v ON_ERROR_STOP=1 -U "$$POSTGRES_USER" -d demo -v start_date="$${BOOKINGS_START_DATE:-2017-01-01}" -v jobs="$(BOOKINGS_JOBS)" <<'"'"'SQL'"'"' + SET bookings.start_date = :'start_date'; + \i /bookings/generate_next_day.sql + RESET bookings.start_date; + SQL' dev-setup: $(UV) python install $(PYTHON_VERSION) diff --git a/README.md b/README.md index 9db8c05..9282f9f 100644 --- a/README.md +++ b/README.md @@ -202,7 +202,8 @@ make logs # Следить за логами Airflow - `BOOKINGS_DB_PASSWORD` — пароль пользователя (по умолчанию: bookings) - `BOOKINGS_DB_NAME` — база данных, из которой запускается установка генератора (по умолчанию: bookings) - `BOOKINGS_DB_PORT` — внешний порт для подключения к контейнеру bookings-db (по умолчанию: 5434) -- `BOOKINGS_START_DATE` — начальная дата модельного времени для первой генерации данных (по умолчанию: 2017-01-01) +- `BOOKINGS_START_DATE` — начальная дата модельного времени для первой генерации данных (по умолчанию: 2017-01-01, генерируем первые сутки сразу после `make bookings-init`) +- `BOOKINGS_JOBS` — число параллельных джобов генератора bookings (по умолчанию: 1) ### CSV pipeline - `CSV_DIR` — путь к каталогу с CSV внутри контейнеров Airflow (по умолчанию: `/opt/airflow/data`) diff --git a/bookings/generate_next_day.sql b/bookings/generate_next_day.sql index e7bb165..2c9d662 100644 --- a/bookings/generate_next_day.sql +++ b/bookings/generate_next_day.sql @@ -1,5 +1,6 @@ --- Генерация ещё одного дня данных в демобазе bookings. -- Если база пуста, берём стартовую дату из параметра :start_date (формат YYYY-MM-DD). +-- psql не умеет подставлять :start_date внутрь DO $$...$$, поэтому прокидываем дату через GUC. +SET bookings.start_date = :'start_date'; DO $$ DECLARE v_max_book_date timestamptz; @@ -15,8 +16,8 @@ BEGIN SELECT max(book_date) INTO v_max_book_date FROM bookings.bookings; IF v_max_book_date IS NULL THEN - -- База пустая: берём стартовую дату из psql-переменной - v_start_date := date_trunc('day', :'start_date'::timestamptz); + -- База пустая: берём стартовую дату из переданного параметра + v_start_date := date_trunc('day', current_setting('bookings.start_date')::timestamptz); ELSE -- Продолжаем с дня, следующего за максимальной датой v_start_date := date_trunc('day', v_max_book_date) + interval '1 day'; @@ -26,9 +27,16 @@ BEGIN -- Первая генерация вызывает generate(), последующие — continue() IF v_max_book_date IS NULL THEN - CALL generate(v_start_date, v_end_date, 1); + CALL generate(v_start_date, v_end_date, :'jobs'); ELSE - CALL continue(v_end_date, 1); + CALL continue(v_end_date, :'jobs'); END IF; -END $$; + -- Ждём завершения фоновых джобов генератора, чтобы данные успели записаться + WHILE busy() LOOP + PERFORM pg_sleep(1); + END LOOP; + PERFORM dblink_disconnect(unnest(dblink_get_connections())); + +END $$; +RESET bookings.start_date; diff --git a/docs/internal/bookings_tz.md b/docs/internal/bookings_tz.md new file mode 100644 index 0000000..0c04a68 --- /dev/null +++ b/docs/internal/bookings_tz.md @@ -0,0 +1,17 @@ +# Временное ТЗ по блоку bookings (для текущей разработки) + +_Этот файл внутренний, удалить перед итоговой сдачей._ + +- Контейнер `bookings-db` — отдельный сервис Postgres из `docker-compose.yml`, база по умолчанию `demo` (из upstream demodb), без переименований. +- Доступ снаружи не блокируем (порт `5434` по умолчанию), чтобы позже читать через PXF и подключаться из Greenplum. +- Инициализация (`make bookings-init`): поднимает контейнер, клонирует demodb (без автопатчей), запускает `install.sql` как есть; генерация стартовых данных должна проходить штатными `generate/continue`. +- Генерация следующего дня: либо `make bookings-generate-day` вызывает `CALL continue(...)`, либо ручной вызов; скрипт `generate_next_day.sql` опционален и не должен менять upstream SQL (только тонкая обертка при желании). +- Исходники demodb: клонировать по требованию с закрепленным коммитом (чтобы не ловить неожиданные изменения). Добавить в `.gitignore`, если не коммитим. Завендорить в репо можно позже, если лицензия позволит. +- Документация: в README описать шаги (`bookings-init`, проверка данных, генерация дня), параметры `.env`, и что настройка PXF/ETL — следующий этап. + +## Текущее состояние +- `Makefile` очищен: убраны автопатчи demodb; добавлены `DEMODB_REPO/DEMODB_COMMIT` с фиксированным хешем `d68de1…`, таргет снова исполняется. `BOOKINGS_JOBS` задаёт число джобов генерации (по умолчанию 1). +- `.gitignore` дополнен `bookings/demodb/` (клонируем по требованию, не коммитим). +- `bookings-init` теперь после установки сразу генерирует 1 день (дата из `BOOKINGS_START_DATE`, по умолчанию 2017-01-01), используя обертку `generate_next_day.sql`. +- `generate_next_day.sql` принимает `:jobs` и ожидает завершения `busy()`, закрывая dblink. +- Генерация через `make` надо подтвердить повторно (в DBeaver генерация работает, но медленно на больших окнах; по умолчанию делаем сутки, далее — по одному дню через `bookings-generate-day`).