# Очередь остаётся своей таблицей, но коллекцией PocketBase - **Дата:** 2026-08-11 - **Источник:** [../research/job-queue.md](../research/job-queue.md) — записка разведки `job-queue-choice` ## Решение Очередь задач остаётся своей таблицей и становится коллекцией 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](../architecture.md) этим решением подтверждён, а не пересмотрен, поэтому парного статуса «заменено на» никакая запись не получает. ## Последствия - `+` очередь видна и правится в панели администратора: мёртвая задача повторяется снятием состояния, а не запросом в консоли сервера. Ровно за это и куплен перевод хранилища на PocketBase ([ADR-2026-08-11-pocketbase-storage-with-admin-panel](ADR-2026-08-11-pocketbase-storage-with-admin-panel.md)). - `+` ни одной новой зависимости: River добавил бы 46 пакетов в сборку, goqite — 3. - `+` захват перестаёт быть двумя запросами без транзакции, и это перестаёт быть местом, которое держится на том, что три воркера читают три разных состояния. - `−` повторы, счётчик попыток и очередь мёртвых пишем сами, и корректность захвата наша. Проверяется это тестами задачи `pocketbase-storage`, а не чужим набором проверок. - `−` захват идёт сырым запросом мимо записей PocketBase: хуки коллекции на нём не срабатывают, и поле времени изменения проставляет наш код. - `−` приборной панели очереди — числа ждущих, упавших, среднего времени — не появляется. Смотрим таблицу коллекции в панели PocketBase, отбирая фильтром.