8. ヘッドレスモード(サーバー)
注釈
このセクションでは、サーバーへのデプロイ、マルチユーザー、自動化を対象とした、blunderDBの高度かつ任意のモードについて説明します。blunderDBの通常かつ推奨される使用方法は、前章で説明したデスクトップアプリケーションのままです。自分のコンピューター上でblunderDBを単独で使用する場合、このモードは必要ありません:分析機能を一切失うことなく、この章を読み飛ばすことができます。
8.1. 概要
同じバイナリ blunderdb は、デスクトップアプリケーションやコマンドライン(コマンドラインインターフェース(CLI) を参照)に加えて、ヘッドレスモード で動作することができます:グラフィカルインターフェースなしで、コマンドラインまたはネットワークから完全に操作されます。このモードは3つの用途をまとめています:
デーモン
serve— blunderDBのエンジンをHTTP + JSONサービスとして公開し、共有データベースをサーバー上で稼働させ、複数人でアクセスできるようにします;汎用ディスパッチャ
call— スクリプティングやテストのために、任意のストレージ操作をローカルで直接呼び出します;migrateコマンド — シングルユーザーのSQLiteデータベースをマルチユーザーのPostgreSQLバックエンドに転送します。
これら3つの用途は、2つのバックエンドと対話できる共通のストレージレイヤーに依存しています:SQLite(デスクトップアプリケーションの通常の .db ファイル形式)と PostgreSQL(マルチユーザーのサーバーデプロイ向け)です。
8.2. デーモン serve
blunderdb serve は、JSONで応答するHTTPサービスとしてエンジンを起動します。これにより、ポジションのデータベースを1台のマシン上でホストし、複数のクライアントからアクセスできるようになります。
# 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…)の背後で動作させる必要があります。決して公開インターネット上に直接公開しないでください。
オプション:
オプション |
デフォルト |
意味 |
|---|---|---|
|
– |
SQLiteファイル( |
|
|
ストレージバックエンド: |
|
|
バックエンドの接続文字列 |
|
|
待ち受けアドレス |
|
|
ログレベル: |
|
|
|
|
– |
このオリジンに対してCORSを有効にする(デフォルトでは無効) |
|
|
テナントごとの秒間リクエスト数の制限(0 = 無効) |
|
|
リクエストのピークに対応するトークンバケットのサイズ |
|
|
PostgreSQL:テナントごとのRow-Level Securityを有効にする(多層防御、オプション) |
|
– |
EPCエンドポイントのレース分析のために内蔵のTS-06-06データベースを拡張する、オプションのtwo-sidedベアオフデータベース( |
ほとんどのオプションは環境変数(BLUNDERDB_BACKEND、BLUNDERDB_DSN、BLUNDERDB_ADDR、BLUNDERDB_LOG_LEVEL、BLUNDERDB_RLS、BLUNDERDB_TS_PATH)でも指定できます。
8.2.1. エンドポイント
サービスは、常に利用可能な運用用のエンドポイントを公開しています:
GET /healthz— 生存確認(プロセスが稼働中);GET /readyz— 準備状態(ストレージが応答している);GET /metrics— Prometheusメトリクス(--metricsが有効な場合)。
La surface métier suit le schéma POST /v1/<famille>.<méthode> (par exemple
/v1/positions.save, /v1/matches.get). Les familles couvrent les
positions, analyses, matchs, commentaires, collections, tournois, cartes Anki,
filtres, sessions, historique (recherche et commandes), recherche,
métadonnées, statistiques, import et export, ainsi que le cycle de vie des
tenants (tenant.purge, réservé au backend PostgreSQL). Les endpoints de
listing renvoient un flux NDJSON (un objet JSON par ligne). Le serveur
s'arrête proprement sur SIGINT / SIGTERM.
positions ファミリーの2つのメソッドは、局面を保存せずにデコードします。positions.fromXGID は XGID 文字列から局面を再構築し、positions.fromXGP は単一局面ファイル .xgp から再構築します。
anki ファミリーには、間隔反復スケジューラ(FSRS)を拡張する6つの新しいメソッドが加わります: anki.reviewLog(各復習の記録 — 評価とFSRSの結果 — 保持率の統計と正確な履歴のため)、anki.forecast(今後数日間に期限が来るカード数の予測、期限超過のカードを含む)、anki.suspendCard / anki.buryCard / anki.removeCard(カードを復習キューから一時的または完全に取り除く)、および anki.optimizeParams(デッキの目標保持率を、その復習で観測された成功率に近づける)。
8.2.2. Docker によるデプロイ
リポジトリには、デーモンの最小限のコンテナイメージを構築する Dockerfile.serve が含まれています:serveバイナリのみがコンパイルされ(純粋なGo、グラフィカルインターフェースなし、CGOなしで静的リンク)、distrolessイメージに配置されます。
# Construire l'image (depuis la racine du dépôt)
docker build -f Dockerfile.serve -t blunderdb-serve .
# Lancer le démon (le backend par défaut de l'image est postgres)
docker run --rm -p 8080:8080 \
-e BLUNDERDB_DSN="postgres://user:pass@hôte:5432/blunderdb?sslmode=disable" \
blunderdb-serve
イメージはポート8080でリッスンし、環境変数(BLUNDERDB_BACKEND、BLUNDERDB_DSN、BLUNDERDB_ADDR、BLUNDERDB_RLS)で設定します。
警告
デーモン自体と同様に、コンテナは一切の認証を行いません:認証を担うリバースプロキシの背後に配置し、決して公開インターネット上に直接公開してはなりません。
8.3. PostgreSQLバックエンドとマルチユーザー
共有デプロイの場合、blunderDBはSQLiteファイルではなく PostgreSQL にデータを保存できます。バックエンドは --backend postgres と接続文字列 --dsn で選択します。スキーマは起動時に自動的に作成・マイグレーションされます。
データはテナント(利用者)ごとに分離されています:各リクエストにはスコープ識別子(ヘッダー X-Tenant-ID、デフォルトは default)が付与され、これにより複数のユーザーが他者のデータを見ることなく同じインスタンスを共有できます。--rls オプションは、補完的にPostgreSQLの Row-Level Security を有効にします:テナントごとの分離ポリシーがインストールされ、app.tenant_id が接続ごとに設定されます。これは任意の多層防御であり、デフォルトでは無効です。
テナントが廃止される際、POST /v1/tenant.purge は現在のテナント(X-Tenant-ID が示すテナント)のすべてのデータ(ポジション、マッチ、コレクション、履歴など)を完全に削除し、そのセッションの状態(最後の検索、最後のポジション、開いているタブ — このスコープを接頭辞とする metadata の数行)も削除します:この操作は単一のトランザクション内で実行され、冪等です(既に空のテナントをパージしてもエラーにはならず、呼び出しを繰り返しても問題ありません)。また、他のテナントにも、スキーマバージョンのグローバルな行にも一切影響しません。この機能はPostgreSQLバックエンドでのみ利用可能で、テナントという概念を持たないSQLiteバックエンドでは invalid エラーを返します。
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
La migration copie les positions, leurs analyses et commentaires, les matchs
(parties + coups), les tournois (avec leurs liens de match) et les collections
(avec leur composition), en réattribuant les clés primaires et étrangères, le
tout dans une seule transaction côté destination : l'opération est atomique
(un échec laisse la destination intacte, il suffit de relancer). La progression
et le bilan final sont émis en NDJSON sur la sortie standard. Si la base source
est assez ancienne pour nécessiter sa propre mise à niveau de schéma sur place,
celle-ci s'exécute d'abord et émet ses propres événements
"schema-migration" (phase/effectué/total) avant que la copie ligne à ligne
ne commence.
オプション |
デフォルト |
意味 |
|---|---|---|
|
– |
ソースのSQLiteデータベース( |
|
– |
宛先のPostgreSQL DSN( |
|
– |
宛先のテナントスコープ( |
|
– |
何も書き込まずに、コピーされる内容を数える |
|
|
|
注釈
アプリケーションの状態は(まだ)移行されません:Ankiのデッキ/カード、フィルターライブラリ、検索およびコマンドの履歴、セッションのメタデータ。優先されるのは、ポジションライブラリとマッチ履歴の移行です。
8.5. 汎用ディスパッチャ call
従来のサブコマンド(コマンドラインインターフェース(CLI))を補完するものとして、blunderdb call はすべてのストレージ操作をローカルで直接公開します。デーモン serve と同じハンドラを経由するため、動作は POST /v1/<famille>.<méthode> と同一です。スクリプティングや統合テストに便利です。
# 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}'
オプション:
オプション |
デフォルト |
意味 |
|---|---|---|
|
– |
SQLiteファイル( |
|
|
|
|
|
バックエンドの接続文字列 |
|
|
テナントスコープ( |
|
|
JSON形式のリクエストボディ |
|
– |
ファイルからリクエストボディを読み込む |
|
– |
すべての |
JSONレスポンス(または *.list エンドポイントの場合はNDJSONストリーム)は標準出力に書き込まれます。エラーが発生した場合、プロセスは非ゼロのコードで終了し、解析可能な状態を保つために(例えば jq で)、{"error":{…}} というエンベロープが標準出力に出力されます。