Files
healthlog/internal/store/migrations/00006_delivery_pending.sql
av 63bffe2865 Приём отвечает 200 до свёртки, свёртку ведёт фоновый воркер
- Очередью служит сама таблица: доставка ждёт свёртки в статусе `pending`,
  канал несёт только бит «есть работа». Переполнять нечего, падение процесса
  очередь не теряет, а подбор `pending` при старте — обычный проход воркера, а
  не отдельный код. Классификация исхода общая с пересборкой журнала.
- Исход разбора начал отражать доставку, а не обстоятельства: отмена и
  занятость базы статус не меняют (иначе конкуренция за базу выводила бы
  доставку из очереди навсегда), паника свёртки больше не валит процесс, а
  учёт доставки идёт через транзакцию с повторами.
- Длинный бюджет ответа выдан маршруту приёма, а не всему серверу:
  `write_timeout` в Go покрывает и чтение тела, и общий подъём снял бы защиту с
  остальных маршрутов.
2026-08-02 11:01:42 +03:00

21 lines
1.6 KiB
SQL

-- +goose Up
-- Очередью свёртки служит сама таблица: доставка ждёт разбора в статусе
-- `pending`, а фоновый воркер выбирает такие строки в порядке журнала. Запрос
-- идёт чаще, чем раз в минуту, а `delivery` растёт примерно на 300 строк в
-- сутки — без индекса это скан всей таблицы с сортировкой на каждый проход.
--
-- Индекс ЧАСТИЧНЫЙ, и это не украшение: в установившемся режиме неразобранных
-- доставок ноль или одна, поэтому индекс держит ноль-одну строку. Полный
-- индекс по `parse_status` хранил бы всю историю (сто тысяч строк в год) ради
-- выборки из одной. SQLite применяет частичный индекс, когда условие запроса
-- следует из условия индекса — наш случай.
--
-- Порядок колонок = порядок журнала, тот же, в котором проигрывает пересборка.
-- Второй ключ обязателен: `received_at` хранится с секундной точностью, и
-- доставки одной секунды без него шли бы в неопределённом порядке.
CREATE INDEX delivery_pending ON delivery (received_at, id)
WHERE parse_status = 'pending';
-- +goose Down
DROP INDEX delivery_pending;