-- 129_avito_full_load_incremental_split.sql
-- Сплит Avito full_load на инкрементальный (daily) + exhaustive (реже).
--
-- Контекст: run_avito_full_load теперь принимает incremental_days. Если задан —
-- fetch_all_secondary(since=date.today()-incremental_days) делает shallow обход с
-- date early-stop → НЕ доходит до глубоких страниц (page-36 429-баны). exhaustive
-- (incremental_days=NULL) дорого и рискованно для бана, но нужен периодически чтобы
-- освежить last_seen (10-дневный delisting TTL) и поймать тихие правки цены.
--
-- ЗАВИСИМОСТИ: 052_scrape_schedules.sql (таблица + UNIQUE(source)),
--             127_scrape_schedules_seed_avito_full_load.sql (seed avito_full_load).
--
-- CADENCE: в scrape_schedules нет колонки interval_minutes/cron — каденс задаётся
-- ключом "interval_days" в default_params (jsonb). scheduler.compute_next_run_at читает
-- его через _claim_run/_defer_next_run_at и откладывает next_run_at на N суток вперёд
-- (отсутствие ключа → 1 = daily, back-compat). avito_full_load_exhaustive получает
-- interval_days=7 → ИСТИННАЯ weekly-периодичность (не эмуляция через single-shot
-- next_run_at). next_run_at тут задаёт лишь ПЕРВЫЙ запуск (стаггер +3 дня от daily-
-- инкремента), дальше строка сама рекуррентит каждые 7 суток. avito_full_load остаётся
-- без interval_days → daily. Колонки строго по схеме 052/127.

BEGIN;

-- ── 1. avito_full_load → инкрементальный (shallow, daily) ────────────────────
-- Мерджим incremental_days=2 в существующий default_params, сохраняя прочие ключи
-- (price_cap_per_bucket, concurrency, request_delay_sec, secondary_only).
-- Идемпотентно: повторный прогон просто перезапишет incremental_days в 2.
-- || перезаписывает только пересекающийся ключ на верхнем уровне jsonb.
UPDATE scrape_schedules
SET default_params = default_params || CAST('{"incremental_days": 2}' AS jsonb),
    updated_at = NOW()
WHERE source = 'avito_full_load';

-- ── 2. avito_full_load_exhaustive → полный обход, weekly (interval_days=7) ────
-- default_params БЕЗ incremental_days → run_avito_full_load(incremental_days=None)
-- → exhaustive bisection. concurrency=1 (агрессивный анти-бан для глубокой пагинации).
-- interval_days=7 → compute_next_run_at откладывает next_run_at на 7 суток после каждого
-- fire = ИСТИННАЯ weekly-периодичность (освежает last_seen 10-дн delisting TTL + ловит
-- тихие правки цены без daily deep-pagination нагрузки).
-- Окно 13:00-15:00 UTC то же что у daily (одна и та же apw-прокси-секция), а первый
-- next_run_at стартует через 3 дня чтобы не пересечься с инкрементальным прогоном.
-- Идемпотентно: ON CONFLICT (source) DO NOTHING — повторный прогон не трогает
-- операторские правки enabled/next_run_at/window.
INSERT INTO scrape_schedules (
    source,
    enabled,
    window_start_hour,
    window_end_hour,
    next_run_at,
    default_params
)
VALUES
(
    'avito_full_load_exhaustive',
    true,
    13,
    15,
    ((CURRENT_DATE + INTERVAL '3 days') + make_interval(hours => 13)) AT TIME ZONE 'UTC',
    CAST(
        '{"price_cap_per_bucket": 1400, "concurrency": 1, "request_delay_sec": 7.0, "secondary_only": true, "interval_days": 7}'
        AS jsonb
    )
)
ON CONFLICT (source) DO NOTHING;

-- Idempotent backfill для interval_days на случай если строка exhaustive уже была
-- засеяна предыдущей версией 129 (без interval_days) до этого деплоя — ON CONFLICT
-- DO NOTHING выше её бы не тронул. Мерджим только ключ interval_days, прочие
-- операторские правки default_params сохраняются (|| перезаписывает лишь этот ключ).
UPDATE scrape_schedules
SET default_params = default_params || CAST('{"interval_days": 7}' AS jsonb),
    updated_at = NOW()
WHERE source = 'avito_full_load_exhaustive'
  AND NOT (default_params ? 'interval_days');

COMMIT;
