- Зачем: - исключить нестабильные режимы генератора, в которых bookings может перестать пополняться. - сделать причину ошибки понятной студенту сразу при запуске команд и SQL-скриптов. - Что: - добавлен precheck `bookings-check-jobs` в Makefile и подключён к `bookings-init` и `bookings-generate-day`. - добавлены явные проверки `bookings.jobs = 1` в `bookings/generate_next_day.sql` и `sql/src/bookings_generate_day_if_missing.sql`. - обновлена документация и `.env.example`: зафиксировано, что в стенде поддерживается только `BOOKINGS_JOBS=1`. - Проверка: - uv run make fmt. - uv run make test. - env BOOKINGS_JOBS=2 make bookings-init. - env BOOKINGS_JOBS=2 make bookings-generate-day. - make bookings-init. - make bookings-generate-day.
55 lines
3.0 KiB
SQL
55 lines
3.0 KiB
SQL
-- Генерация учебного дня в демо-БД bookings.
|
|
-- Этот скрипт всегда добавляет следующий учебный день после максимальной даты
|
|
-- в таблице bookings.bookings (или несколько дней от стартовой даты, если база пуста).
|
|
-- Логическая дата запуска DAG ({{ ds }}) используется только как метка батча в стейдже.
|
|
|
|
DO $$
|
|
DECLARE
|
|
v_max_book_date timestamptz;
|
|
v_start_date timestamptz;
|
|
v_end_date timestamptz;
|
|
v_jobs integer := COALESCE(current_setting('bookings.jobs', true), '1')::integer;
|
|
v_init_days integer := COALESCE(current_setting('bookings.init_days', true), '1')::integer;
|
|
v_start_cfg text := COALESCE(current_setting('bookings.start_date', true), '2017-01-01');
|
|
BEGIN
|
|
-- Проверяем, что демобаза установлена
|
|
IF to_regclass('bookings.bookings') IS NULL THEN
|
|
RAISE EXCEPTION 'Таблица bookings.bookings не найдена. Сначала выполните make bookings-init.';
|
|
END IF;
|
|
|
|
-- В учебном стенде поддерживается только jobs=1, иначе генерация нестабильна.
|
|
IF v_jobs <> 1 THEN
|
|
RAISE EXCEPTION 'Поддерживается только bookings.jobs=1. Текущее значение: %. Установите BOOKINGS_JOBS=1 и выполните make bookings-init.', v_jobs;
|
|
END IF;
|
|
|
|
-- Ищем последнюю сгенерированную дату
|
|
SELECT max(book_date) INTO v_max_book_date FROM bookings.bookings;
|
|
|
|
IF v_max_book_date IS NULL THEN
|
|
-- База пустая: берём стартовую дату из конфигурации (или дефолтную)
|
|
v_start_date := date_trunc('day', v_start_cfg::timestamptz);
|
|
ELSE
|
|
-- Продолжаем с дня, следующего за максимальной датой
|
|
v_start_date := date_trunc('day', v_max_book_date) + interval '1 day';
|
|
END IF;
|
|
|
|
-- Первая генерация вызывает generate(), последующие — continue()
|
|
IF v_max_book_date IS NULL THEN
|
|
v_end_date := v_start_date + (v_init_days || ' days')::interval;
|
|
CALL generate(v_start_date, v_end_date, v_jobs);
|
|
ELSE
|
|
v_end_date := v_start_date + interval '1 day';
|
|
CALL continue(v_end_date, v_jobs);
|
|
END IF;
|
|
|
|
RAISE NOTICE 'Сгенерированы данные в bookings.bookings за интервал [% - %).',
|
|
date_trunc('day', v_start_date),
|
|
date_trunc('day', v_end_date);
|
|
|
|
-- Ждём завершения фоновых джобов генератора, чтобы данные успели записаться
|
|
WHILE busy() LOOP
|
|
PERFORM pg_sleep(1);
|
|
END LOOP;
|
|
PERFORM dblink_disconnect(unnest(dblink_get_connections()));
|
|
END $$;
|