80_complexes_backfill_nulls.sql: - cad_quarter: +722 rows via ST_Contains spatial join on cad_quarters_geom - developer_id: +247 rows via fuzzy name match on domrf_developers - obj_class: +2 rows via objective_lots.class mode - cad_building_num TEXT dropped (100% NULL; relation lives in cad_buildings.complex_id) - v_complex_full rebuilt: cad_building_nums TEXT[] replaces dead column - v_complex_buildings created: complex_id → cad_building_nums[], buildings_count 81_job_settings.sql: - New table job_settings (job_type PK, enabled, queue_name, cron_schedule, rate_ms, max_retries, max_concurrency, extra_config JSONB) - Seeded 4 rows: scrape_kn (queue=scrape_kn, '15 4 * * mon'), nspd_geo (queue=geo, rate_ms=600), objective_etl, objective_sync (cron from prod objective_sync_config) - objective_sync_config marked DEPRECATED via COMMENT — kept for backward compat until backend refactor Both already applied on prod via postgres MCP. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
143 lines
6.8 KiB
PL/PgSQL
143 lines
6.8 KiB
PL/PgSQL
-- Централизованная таблица настроек для всех Celery-job'ов.
|
||
--
|
||
-- Контекст:
|
||
-- До этой миграции конфиг был разбросан по трём местам:
|
||
-- • scrape_kn — env-переменные SCRAPE_KN_CRON / SCRAPE_KN_DEFAULT_REGIONS
|
||
-- • nspd_geo — per-row rate_ms в nspd_geo_jobs (нет global default)
|
||
-- • objective_etl — hardcode в settings + env OBJECTIVE_ANTON_SQLITE_PATH
|
||
-- • objective_sync — уже в objective_sync_config (оставляем как deprecated fallback)
|
||
--
|
||
-- Цель: единая таблица job_settings — один UI /admin/jobs/settings для всех job'ов.
|
||
--
|
||
-- Зависимости:
|
||
-- Нет FK на другие таблицы. objective_sync_config НЕ дропается — она помечается
|
||
-- DEPRECATED и остаётся как fallback для уже задеплоенного backend-кода.
|
||
--
|
||
-- Порядок применения:
|
||
-- Применяется один раз на чистой или работающей БД.
|
||
-- Идемпотентно (CREATE IF NOT EXISTS + INSERT ON CONFLICT DO NOTHING).
|
||
-- Backend-код должен быть задеплоен ПОСЛЕ этой миграции.
|
||
--
|
||
-- Проверка после применения:
|
||
-- SELECT * FROM job_settings; -- должна вернуть 4 строки
|
||
-- SELECT * FROM objective_sync_config; -- должна по-прежнему работать
|
||
|
||
BEGIN;
|
||
|
||
-- ── Создание таблицы ─────────────────────────────────────────────────────────
|
||
|
||
CREATE TABLE IF NOT EXISTS job_settings (
|
||
job_type TEXT PRIMARY KEY,
|
||
-- 'scrape_kn' | 'nspd_geo' | 'objective_etl' | 'objective_sync'
|
||
enabled BOOLEAN NOT NULL DEFAULT true,
|
||
queue_name TEXT NOT NULL DEFAULT 'celery',
|
||
-- celery (default) | scrape_kn | geo
|
||
cron_schedule TEXT,
|
||
-- Стандартный crontab: 'minute hour dom month dow'. NULL = только ручной запуск.
|
||
rate_ms INTEGER,
|
||
-- Пауза между API-запросами (мс). NULL/0 = не throttled.
|
||
max_retries SMALLINT NOT NULL DEFAULT 2,
|
||
max_concurrency SMALLINT NOT NULL DEFAULT 1,
|
||
-- Макс. параллельных task'ов этого типа.
|
||
extra_config JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||
-- Job-specific: {"regions":[66], "groups_csv":"...", "sqlite_path":"..."}.
|
||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||
updated_by TEXT,
|
||
description TEXT
|
||
-- Человеко-читаемое описание для UI.
|
||
);
|
||
|
||
COMMENT ON TABLE job_settings IS
|
||
'Centralized settings for all Celery jobs. See /admin/jobs/settings UI. '
|
||
'Replaces scattered env vars and per-table configs.';
|
||
|
||
COMMENT ON COLUMN job_settings.queue_name IS
|
||
'Celery queue routing. Allows concurrency between job types within one worker container.';
|
||
|
||
COMMENT ON COLUMN job_settings.cron_schedule IS
|
||
'Standard crontab string (5-field: minute hour dom month dow). '
|
||
'NULL = manual trigger only. Beat re-reads on restart.';
|
||
|
||
COMMENT ON COLUMN job_settings.rate_ms IS
|
||
'Delay between API calls in milliseconds (used by NSPD geo). NULL/0 for non-throttled jobs.';
|
||
|
||
COMMENT ON COLUMN job_settings.extra_config IS
|
||
'Job-specific JSON config: e.g. {"regions":[66,77], "groups_csv":"Свердловская область,...", '
|
||
'"sqlite_path":"/data/anton-sqlite/analysis.db"}.';
|
||
|
||
-- ── Seed данные ───────────────────────────────────────────────────────────────
|
||
-- ON CONFLICT DO NOTHING — безопасен при повторном запуске.
|
||
-- Defaults взяты из:
|
||
-- scrape_kn → backend/app/core/config.py (scrape_kn_cron / scrape_kn_default_regions)
|
||
-- nspd_geo → nspd_geo_jobs.rate_ms most common value (600) на проде
|
||
-- objective_etl → backend/app/core/config.py (objective_anton_sqlite_path)
|
||
-- objective_sync → objective_sync_config.cron_schedule (prod value '0 6 * * tue')
|
||
|
||
INSERT INTO job_settings
|
||
(job_type, enabled, queue_name, cron_schedule, rate_ms, max_retries,
|
||
max_concurrency, extra_config, description)
|
||
VALUES
|
||
(
|
||
'scrape_kn',
|
||
true,
|
||
'scrape_kn',
|
||
'15 4 * * mon',
|
||
NULL,
|
||
2,
|
||
1,
|
||
'{"default_regions": [66]}'::jsonb,
|
||
'Скрейпинг КН (ЦИАН): загрузка объявлений по регионам. '
|
||
'Расписание и регионы ранее задавались через env SCRAPE_KN_CRON / SCRAPE_KN_DEFAULT_REGIONS.'
|
||
),
|
||
(
|
||
'nspd_geo',
|
||
true,
|
||
'geo',
|
||
NULL,
|
||
600,
|
||
2,
|
||
1,
|
||
'{}'::jsonb,
|
||
'Геокодирование объектов через НСПД/rosreestr2coord. '
|
||
'Запускается вручную по job-конфигурациям nspd_geo_jobs. rate_ms — глобальный дефолт.'
|
||
),
|
||
(
|
||
'objective_etl',
|
||
true,
|
||
'celery',
|
||
NULL,
|
||
NULL,
|
||
2,
|
||
1,
|
||
'{"sqlite_path": "/data/anton-sqlite/analysis.db"}'::jsonb,
|
||
'ETL: SQLite Антоновского → PG (objective_* таблицы). '
|
||
'Запускается вручную. sqlite_path ранее задавался через env OBJECTIVE_ANTON_SQLITE_PATH.'
|
||
),
|
||
(
|
||
'objective_sync',
|
||
true,
|
||
'celery',
|
||
'0 6 * * tue',
|
||
NULL,
|
||
2,
|
||
1,
|
||
'{
|
||
"groups_csv": "Свердловская область,Челябинск,Тюмень,Пермь",
|
||
"use_ddu": true,
|
||
"use_dkp": true,
|
||
"period_months_back": 1,
|
||
"inter_group_delay_s": 30,
|
||
"rate_ms": 3000
|
||
}'::jsonb,
|
||
'Синхронизация DOM.РФ Objective (отчёты). '
|
||
'Детальный конфиг дублирован в objective_sync_config (deprecated legacy fallback).'
|
||
)
|
||
ON CONFLICT (job_type) DO NOTHING;
|
||
|
||
-- ── Пометить objective_sync_config как deprecated ─────────────────────────────
|
||
-- Таблица НЕ дропается: backend продолжает читать её как fallback до рефакторинга.
|
||
COMMENT ON TABLE objective_sync_config IS
|
||
'DEPRECATED: use job_settings (job_type=''objective_sync'') for new config reads. '
|
||
'Kept for backward compat until backend refactor. Do NOT drop until refactor is deployed.';
|
||
|
||
COMMIT;
|