8. Безголовый режим (сервер)

Примечание

Этот раздел описывает продвинутый и необязательный режим blunderDB, предназначенный для серверных развёртываний, многопользовательской работы и автоматизации. Обычным и рекомендуемым способом использования blunderDB остаётся настольное приложение, описанное в предыдущих главах. Если вы используете blunderDB в одиночку, на своём компьютере, этот режим вам не нужен: вы можете пропустить эту главу, не теряя ни одной функции анализа.

8.1. Обзор

Тот же исполняемый файл blunderdb может, помимо настольного приложения и команд командной строки (см. Интерфейс командной строки (CLI)), работать в безголовом режиме: без графического интерфейса, полностью управляемый из командной строки или по сети. Этот режим объединяет три варианта использования:

  • демон serve — предоставляет движок blunderDB как сервис HTTP + JSON, чтобы держать общую базу на сервере и обращаться к ней с нескольких клиентов;

  • универсальный диспетчер call — вызывает любую операцию хранения напрямую, локально, для написания скриптов и тестов;

  • команда migrate — переносит однопользовательскую базу SQLite в многопользовательский бэкенд PostgreSQL.

Эти три варианта использования опираются на общий слой хранения, который умеет работать с двумя бэкендами: SQLite (привычный формат файла .db настольного приложения) и PostgreSQL (для многопользовательских серверных развёртываний).

8.2. Демон serve

blunderdb serve запускает движок как сервис HTTP, отвечающий в формате JSON. Он позволяет разместить базу позиций на одной машине и обращаться к ней с нескольких клиентов.

# Servir une base SQLite locale sur le port 8080
blunderdb serve --db ma_base.db --addr :8080

# Servir un backend PostgreSQL
blunderdb serve --backend postgres \
    --dsn "postgres://user:pass@host:5432/blunderdb?sslmode=disable" \
    --addr :8080

Предупреждение

Демон не выполняет никакой аутентификации. Он доверяет заголовку запроса X-Tenant-ID и должен работать за обратным прокси (nginx, Caddy…), отвечающим за аутентификацию. Никогда не выставляйте его напрямую в публичный Интернет.

Опции:

Опция

По умолчанию

Значение

--db <путь>

файл SQLite (сокращение для --backend sqlite --dsn <chemin>)

--backend <type>

sqlite

бэкенд хранения: sqlite или postgres

--dsn <строка>

$BLUNDERDB_DSN

строка подключения к бэкенду

--addr <хост:порт>

:8080

адрес прослушивания

--log-level <уровень>

info

уровень журналирования: debug|info|warn|error

--metrics

true

предоставляет /metrics (формат Prometheus)

--cors-allow-origin <источник>

включает CORS для этого источника (по умолчанию отключено)

--rate-limit-rps <n>

0

лимит запросов в секунду на одного арендатора (0 = отключено)

--rate-limit-burst <n>

2×rps

размер корзины токенов для пиков запросов

--rls

false

PostgreSQL: включает Row-Level Security по арендаторам (глубокая защита, по выбору)

Большинство опций можно также задать через переменные окружения (BLUNDERDB_BACKEND, BLUNDERDB_DSN, BLUNDERDB_ADDR, BLUNDERDB_LOG_LEVEL, BLUNDERDB_RLS).

8.2.1. Точки доступа

Сервис предоставляет эксплуатационные точки доступа, всегда присутствующие:

  • GET /healthz — живучесть (процесс работает);

  • GET /readyz — готовность (хранилище отвечает);

  • GET /metrics — метрики Prometheus (если активна опция --metrics).

Прикладная поверхность следует схеме POST /v1/<семейство>.<метод> (например, /v1/positions.save, /v1/matches.get). Семейства охватывают позиции, анализы, матчи, комментарии, коллекции, турниры, карточки Anki, фильтры, сессии, поиск, метаданные, статистику и импорт. Эндпоинты списков возвращают поток NDJSON (по одному объекту JSON на строку). Сервер корректно останавливается по SIGINT / SIGTERM.

Два метода семейства positions декодируют позицию, не сохраняя её: positions.fromXGID восстанавливает позицию из строки XGID, а positions.fromXGP — из файла одиночной позиции .xgp.

8.3. Бэкенд PostgreSQL и многопользовательский режим

Для общего развёртывания blunderDB может хранить данные в PostgreSQL, а не в файле SQLite. Бэкенд выбирается опцией --backend postgres и строкой подключения --dsn. Схема создаётся и мигрируется автоматически при запуске.

Данные разделены по арендаторам (tenant): каждый запрос несёт идентификатор области (заголовок X-Tenant-ID, по умолчанию default), что позволяет нескольким пользователям совместно использовать один экземпляр, не видя данных друг друга. Опция --rls дополнительно включает Row-Level Security PostgreSQL: устанавливаются политики изоляции по арендаторам, а app.tenant_id задаётся для каждого соединения. Это необязательная глубокая защита, отключённая по умолчанию.

8.4. Миграция базы SQLite в PostgreSQL

blunderdb migrate копирует однопользовательскую базу SQLite в бэкенд PostgreSQL под выбранной областью арендатора — это путь для «загрузки» настольной библиотеки в серверное развёртывание.

blunderdb migrate \
    --from sqlite:///chemin/vers/base.db \
    --to   "postgres://user:pass@host:5432/db?sslmode=disable" \
    --tenant-id mon-tenant

# Prévisualiser sans rien écrire
blunderdb migrate --from sqlite:///chemin/vers/base.db \
    --tenant-id mon-tenant --dry-run

Миграция копирует позиции, их анализы и комментарии, матчи (партии + ходы), турниры (с их связями матчей) и коллекции (с их составом), переназначая первичные и внешние ключи, всё в одной транзакции на стороне назначения: операция атомарна (сбой оставляет назначение нетронутым, достаточно повторить запуск). Прогресс и итоговый отчёт выводятся в NDJSON на стандартный вывод.

Опция

По умолчанию

Значение

--from <uri>

исходная база SQLite (sqlite:///chemin или просто путь)

--to <dsn>

DSN PostgreSQL назначения (postgres://…)

--tenant-id <scope>

область арендатора назначения (обязательна, кроме режима --dry-run)

--dry-run

подсчитывает, что было бы скопировано, ничего не записывая

--on-conflict <политика>

""

"" прерывает, если у арендатора уже есть данные; skip объединяет (дедупликация позиций по хешу Zobrist)

Примечание

Пока (ещё) не мигрируются прикладные состояния: колоды/карточки Anki, библиотека фильтров, история поиска и команд, а также метаданные сессии. Приоритет — миграция библиотеки позиций и истории матчей.

8.5. Универсальный диспетчер call

В дополнение к историческим подкомандам (Интерфейс командной строки (CLI)), blunderdb call предоставляет все операции хранения напрямую, локально. Он проходит через те же обработчики, что и демон serve: поэтому поведение идентично POST /v1/<семейство>.<метод>. Это полезно для написания скриптов и интеграционного тестирования.

# Lister toutes les méthodes disponibles
blunderdb call --list

# Lectures
blunderdb call metadata.counts --db ma_base.db
blunderdb call positions.list  --db ma_base.db --json '{"limit":10}'
blunderdb call matches.get     --db ma_base.db --json '{"id":1}'

# Écritures
blunderdb call positions.save  --db ma_base.db --json '{"position":{...}}'
blunderdb call matches.delete  --db ma_base.db --json '{"id":42}'

Опции:

Опция

По умолчанию

Значение

--db <путь>

файл SQLite (сокращение для --backend sqlite --dsn <chemin>)

--backend <type>

sqlite

sqlite или postgres

--dsn <строка>

$BLUNDERDB_DSN

строка подключения к бэкенду

--scope <строка>

default

область арендатора (отправляется как X-Tenant-ID)

--json <строка>

{}

тело запроса в формате JSON

--json-file <путь>

читает тело запроса из файла

--list

выводит все методы <семейство>.<метод> и завершает работу

Ответ JSON (или поток NDJSON для эндпоинтов *.list) записывается на стандартный вывод. В случае ошибки процесс завершается с ненулевым кодом, а оболочка {"error":{…}} выводится на стандартный вывод, чтобы оставаться разбираемой (например, с помощью jq).