- база своя: два пула, захват одним UPDATE ... RETURNING, шаги схемы на goose под файловым замком, одна миграция начальной схемы вместо семи прежних - транспорт переписан на net/http: свои слои, свой ограничитель частоты, отдача файла с проверкой владельца; панель /_/ и пространство /api/ исчезли - по находкам ревью: журнал не пишет путь под корнем приложения, ключ бюджета читается справа налево, узнавание известного идёт читающим пулом
8.1 KiB
Хранилищем становится SQLite с каталогом файлов, а PocketBase уходит целиком
- Дата: 2026-08-22
- Источник: ../research/storage-without-pocketbase.md — записка разведки о выборе хранилища
Решение
PocketBase уходит из проекта целиком: состояние записей и метаданные переезжают
в SQLite, с которым сервис работает напрямую через modernc.org/sqlite, файлы
записей — в свой каталог со своей раскладкой, маршруты и слои — на net/http,
шаги схемы — на свой раннер. Панель администратора теряется и не заменяется
ничем: пока идёт стройка, остановленную запись возвращает в работу запрос к
базе.
Два решения абзаца выше сменились при разметке изменения, и заменившее названо здесь.
Шаги схемы двигает библиотека github.com/pressly/goose/v3, а не свой раннер.
Инструмент выбрал владелец 2026-08-22: библиотека уже была в этом проекте и ушла
вместе с PocketBase, а из трёх норм, которые накат обязан выполнять, две
выполняет сама.
Остановленную запись возвращает в работу подкоманда cmd/devtools resume, а не
запрос к базе руками. Возврат сбрасывает не одно поле записи и пишет событие
журнала с происхождением entity.EventOriginHuman; рука за клавиатурой не делает
ни того, ни другого. Последствие ниже — «возврат остановленной в работу […]
делает запрос к базе руками» — читается этой сменой.
Доводы обоих решений записаны в
design.md,
разделы «Шаги схемы двигает goose, а не свой раннер» и «Панель не заменяется
ничем, а возврат в работу делает подкоманда оснастки».
Запись заменяет три: ADR-2026-08-11-pocketbase-storage-with-admin-panel, ADR-2026-08-11-queue-as-pocketbase-collection и ADR-2026-08-12-protected-file-behind-session.
Что из заменённых решений подтверждается, а не отменяется. Очередь остаётся
своей таблицей, захват — одним запросом с RETURNING, готовую библиотеку
очереди по-прежнему не берём: замер, которым это решено, снят на
modernc.org/sqlite — том самом драйвере, который остаётся и после ухода.
Отменяется у той записи одно слово: таблица перестаёт быть коллекцией.
Приложение остаётся в своём корне /app/
(ADR-2026-08-15-app-namespace). Файл записи
остаётся закрытым — но проверкой владельца в своём обработчике, а не защищённым
полем коллекции и коротким токеном.
Почему
Разведка мерила не «хранилище против хранилища», а то, что библиотека держит в этом коде. Цитата из источника:
Разрез «хранилище против хранилища» вопроса не покрывает: библиотека держит шесть ролей сразу, и только две из них про хранение.
Довод, на котором стоял перевод, отпал сам. Источник, раздел о трёх доводах:
Вход делает само приложение с 2026-08-22 […]: пришедшего называет заголовок прокси, а учётную запись заводит наш
EnsureUser. Пользователи в коллекции есть потому, что их пишет наш код, а не провайдер библиотеки. Довод, которым отвергнут отвергнутый вариант, перестал быть верным.
Отвергнут вариант «уйти в два шага», оставив панель жить в промежутке, и отвергнут решением владельца: панель на стройке заменяется запросом к базе, а вторая порция работы стоит дороже, чем то, что она сберегает.
Обстоятельство, которое назначило момент:
на сервере данных нет и сервис остановлен, поэтому смена стоит только кода. Дешевле она не станет никогда — каталог
internal/controller/httpприрастает кодом на чужих типах с каждой задачей.
Последствия
+периметр сервиса становится только нашим. Панель/_/исчезает вместе с дефектом/%5f/из ../security.md, а пространство хранилища/api/— вместе с необходимостью держать его открытым ради файлов.+пропадает секрет, которого не было до перевода, — пароль суперпользователя панели.+файлы ложатся своей раскладкой, и загрузка частями, узнавание по хеш-сумме, удаление записи и вторая копия рядом становятся обычной работой с файлами.+из сборки уходят шесть модулей, достижимых только через библиотеку:imaging,mailyak,jwt,fexpr,cobra, драйвер MySQL.modernc.org/sqliteостаётся, и сборка по-прежнему обходится без CGO.−владелец сервиса остаётся без панели. Правку записи, возврат остановленной в работу и просмотр очереди до появления экранов делает запрос к базе руками. Задачиaudiorecord-actionsиplay-recording-in-appэтим становятся не улучшением, а заменой утраченного инструмента.−шаги схемы, отдачу файла, ограничитель частоты и настройку базы пишем и сопровождаем сами. Единственный писатель уmodernc.org/sqlite— наша забота с этого дня.−раскладка каталога данных меняется необратимо. Цена сегодня нулевая: стройка, на сервере пусто; после первой боевой записи она перестаёт быть нулевой.−1497 строк контроллера и 3075 строк его проверок написаны на*core.RequestEventи переписываются целиком.