Files
transcriber/docs/adr/ADR-2026-08-11-queue-as-pocketbase-collection.md
T
av ad5b5e377f записано решение уйти с PocketBase на SQLite со своим каталогом файлов
- разведка storage-without-pocketbase: шесть ролей библиотеки в этом коде, отпавший довод перевода, шесть модулей достижимы только через неё
- ADR-2026-08-22-storage-without-pocketbase заменяет три записи: перевод в PocketBase, очередь коллекцией, файл за защищённым полем
- задача storage-without-pocketbase встала первой строкой плана стройки
2026-08-22 21:00:14 +03:00

5.2 KiB
Raw Blame History

Очередь остаётся своей таблицей, но коллекцией PocketBase

Решение

Очередь задач остаётся своей таблицей и становится коллекцией PocketBase: захват идёт одним запросом с RETURNING, число попыток лежит колонкой, нарастающая пауза выражается существующим delay_time, а исчерпавшая попытки задача переходит в состояние «мертва» вместо сегодняшнего is_error = 1. Готовую библиотеку очереди не берём.

Почему

Разведка искала готовую очередь и нашла, что для PocketBase её нет:

Единственная очередь в списке — pocketbase-queue, написана на TypeScript и работает из JS-хуков; из Go её не подключить.

Отсюда разрез, который и решил дело:

выбор идёт не между готовым и своим, а между своим в коллекции PocketBase и чужой очередью, живущей рядом с PocketBase и мимо её панели. River и goqite про PocketBase не знают.

Главный довод в пользу чужой библиотеки — транзакционный захват — снялся замером:

движок за modernc.org/sqlite v1.55.0 — версии 3.53.3, RETURNING в нём есть, и на трёх горутинах разом запись получила ровно одна. Это снимает главный довод в пользу чужой библиотеки: транзакционность захвата покупается одной строкой запроса, а не новой зависимостью.

Отвергнуты два кандидата, и оба с названной ценой:

River с драйвером SQLite — покупает повторы, счётчик и мёртвых готовыми, но выносит очередь из панели PocketBase, ради которой хранилище и переезжает, и переписывает конвейер в цепочку задач.

goqite — не отвечает ни на один из трёх вопросов задачи целиком, а его предел выдач молча теряет запись.

Запись попадает в журнал как намеренный отказ от очевидного подхода: взять готовую библиотеку вместо своего кода — первое, что предлагают на такой вопрос, и без записанной причины его предложат снова. Принцип «очередь таблицей» из ../architecture.md этим решением подтверждён, а не пересмотрен, поэтому парного статуса «заменено на» никакая запись не получает.

Последствия

  • + очередь видна и правится в панели администратора: мёртвая задача повторяется снятием состояния, а не запросом в консоли сервера. Ровно за это и куплен перевод хранилища на PocketBase (ADR-2026-08-11-pocketbase-storage-with-admin-panel).
  • + ни одной новой зависимости: River добавил бы 46 пакетов в сборку, goqite — 3.
  • + захват перестаёт быть двумя запросами без транзакции, и это перестаёт быть местом, которое держится на том, что три воркера читают три разных состояния.
  • повторы, счётчик попыток и очередь мёртвых пишем сами, и корректность захвата наша. Проверяется это тестами задачи pocketbase-storage, а не чужим набором проверок.
  • захват идёт сырым запросом мимо записей PocketBase: хуки коллекции на нём не срабатывают, и поле времени изменения проставляет наш код.
  • приборной панели очереди — числа ждущих, упавших, среднего времени — не появляется. Смотрим таблицу коллекции в панели PocketBase, отбирая фильтром.