fix(bookings): устранено зависание генерации при jobs>1 и убран VACUUM из инкрементов

- Зачем:
  - 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>
This commit is contained in:
2026-03-09 16:30:13 +03:00
co-authored by Claude Opus 4.6
parent 78fb8e372c
commit 85d2776b44
2 changed files with 30 additions and 16 deletions
+16 -8
View File
@@ -35,6 +35,12 @@ BEGIN
CALL generate(v_start_date, v_end_date, v_jobs); CALL generate(v_start_date, v_end_date, v_jobs);
ELSE ELSE
v_end_date := v_start_date + interval '1 day'; v_end_date := v_start_date + interval '1 day';
-- Убираем VACUUM-ивенты из очереди: генератор demodb кладёт
-- VACUUM ANALYZE всей БД каждую неделю модельного времени.
-- На 500k+ строках это занимает минуты и бессмысленно для +1 дня.
DELETE FROM gen.events WHERE type = 'VACUUM';
CALL continue(v_end_date, v_jobs); CALL continue(v_end_date, v_jobs);
END IF; END IF;
@@ -42,17 +48,19 @@ BEGIN
-- Без COMMIT воркеры не могут INSERT INTO gen.stat_jobs → deadlock. -- Без COMMIT воркеры не могут INSERT INTO gen.stat_jobs → deadlock.
COMMIT; COMMIT;
-- При jobs>1 воркерам нужно время, чтобы подключиться через dblink и -- Ждём завершения каждого воркера через dblink_is_busy().
-- выставить application_name='Airlines processor'. Без паузы busy() -- Раньше опрашивали busy() (pg_stat_activity + application_name),
-- сразу вернёт false (воркеры ещё не видны в pg_stat_activity). -- но это ненадёжно: воркер может обрабатывать VACUUM ANALYZE (десятки минут),
-- или зависнуть в пустой очереди — а busy() не отличает «полезную работу»
-- от «бесконечного pg_sleep(1) при пустом gen.events».
-- dblink_is_busy() проверяет состояние конкретного dblink-соединения напрямую.
IF v_jobs > 1 THEN IF v_jobs > 1 THEN
PERFORM pg_sleep(3); FOR i IN 1 .. v_jobs LOOP
END IF; WHILE dblink_is_busy('job' || i) = 1 LOOP
-- Ждём завершения фоновых джобов генератора, чтобы данные успели записаться
WHILE busy() LOOP
PERFORM pg_sleep(1); PERFORM pg_sleep(1);
END LOOP; END LOOP;
END LOOP;
END IF;
PERFORM dblink_disconnect(unnest(dblink_get_connections())); PERFORM dblink_disconnect(unnest(dblink_get_connections()));
-- Если данных нет, останавливаемся с понятной ошибкой -- Если данных нет, останавливаемся с понятной ошибкой
+12 -6
View File
@@ -38,6 +38,12 @@ BEGIN
CALL generate(v_start_date, v_end_date, v_jobs); CALL generate(v_start_date, v_end_date, v_jobs);
ELSE ELSE
v_end_date := v_start_date + interval '1 day'; v_end_date := v_start_date + interval '1 day';
-- Убираем VACUUM-ивенты из очереди: генератор demodb кладёт
-- VACUUM ANALYZE всей БД каждую неделю модельного времени.
-- На 500k+ строках это занимает минуты и бессмысленно для +1 дня.
DELETE FROM gen.events WHERE type = 'VACUUM';
CALL continue(v_end_date, v_jobs); CALL continue(v_end_date, v_jobs);
END IF; END IF;
@@ -49,14 +55,14 @@ BEGIN
date_trunc('day', v_start_date), date_trunc('day', v_start_date),
date_trunc('day', v_end_date); date_trunc('day', v_end_date);
-- При jobs>1 воркерам нужно время, чтобы подключиться через dblink -- Ждём завершения каждого воркера через dblink_is_busy() (см. комментарий
-- в bookings/generate_next_day.sql — busy() через pg_stat_activity ненадёжен).
IF v_jobs > 1 THEN IF v_jobs > 1 THEN
PERFORM pg_sleep(3); FOR i IN 1 .. v_jobs LOOP
END IF; WHILE dblink_is_busy('job' || i) = 1 LOOP
-- Ждём завершения фоновых джобов генератора, чтобы данные успели записаться
WHILE busy() LOOP
PERFORM pg_sleep(1); PERFORM pg_sleep(1);
END LOOP; END LOOP;
END LOOP;
END IF;
PERFORM dblink_disconnect(unnest(dblink_get_connections())); PERFORM dblink_disconnect(unnest(dblink_get_connections()));
END $$; END $$;