8. Λειτουργία χωρίς γραφικό περιβάλλον (διακομιστής)

Σημείωση

Αυτή η ενότητα περιγράφει μια προηγμένη και προαιρετική λειτουργία του blunderDB, που προορίζεται για αναπτύξεις σε διακομιστή, για πολλαπλούς χρήστες και για αυτοματοποίηση. Η συνήθης και συνιστώμενη χρήση του blunderDB παραμένει η εφαρμογή γραφείου που περιγράφεται στα προηγούμενα κεφάλαια. Αν χρησιμοποιείτε το blunderDB μόνοι σας, στον υπολογιστή σας, δεν χρειάζεστε αυτή τη λειτουργία: μπορείτε να αγνοήσετε αυτό το κεφάλαιο χωρίς να χάσετε καμία από τις λειτουργίες ανάλυσης.

8.1. Επισκόπηση

Το ίδιο εκτελέσιμο blunderdb μπορεί, εκτός από την εφαρμογή γραφείου και τις εντολές γραμμής εντολών (δείτε Διεπαφή γραμμής εντολών (CLI)), να λειτουργήσει σε λειτουργία χωρίς γραφικό περιβάλλον: χωρίς γραφική διεπαφή, ελεγχόμενο εξ ολοκλήρου μέσω της γραμμής εντολών ή μέσω δικτύου. Αυτή η λειτουργία συγκεντρώνει τρεις χρήσεις:

  • ο δαίμονας serve — εκθέτει τη μηχανή του blunderDB ως υπηρεσία HTTP + JSON, για να τρέχει μια κοινόχρηστη βάση σε διακομιστή και να την προσπελάζουν πολλοί χρήστες·

  • ο γενικός dispatcher call — καλεί οποιαδήποτε λειτουργία αποθήκευσης απευθείας, τοπικά, για scripting και δοκιμές·

  • η εντολή migrate — μεταφέρει μια βάση SQLite ενός χρήστη προς ένα backend PostgreSQL πολλαπλών χρηστών.

Αυτές οι τρεις χρήσεις βασίζονται σε ένα κοινό επίπεδο αποθήκευσης που γνωρίζει να επικοινωνεί με δύο backend: το 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 και πρέπει να τρέχει πίσω από έναν reverse-proxy (nginx, Caddy…) υπεύθυνο για την πιστοποίηση ταυτότητας. Μην τον εκθέτετε ποτέ απευθείας στο δημόσιο Διαδίκτυο.

Επιλογές:

Επιλογή

Προεπιλογή

Σημασία

--db <chemin>

αρχείο SQLite (συντόμευση για --backend sqlite --dsn <chemin>)

--backend <type>

sqlite

backend αποθήκευσης: sqlite ή postgres

--dsn <chaîne>

$BLUNDERDB_DSN

συμβολοσειρά σύνδεσης του backend

--addr <hôte:port>

:8080

διεύθυνση ακρόασης

--log-level <niveau>

info

επίπεδο καταγραφής: debug|info|warn|error

--metrics

true

εκθέτει το /metrics (μορφή Prometheus)

--cors-allow-origin <origine>

ενεργοποιεί CORS για αυτή την προέλευση (απενεργοποιημένο εξ ορισμού)

--rate-limit-rps <n>

0

όριο αιτημάτων ανά δευτερόλεπτο και ανά tenant (0 = απενεργοποιημένο)

--rate-limit-burst <n>

2×rps

μέγεθος του κάδου διακριτικών (token bucket) για τις αιχμές αιτημάτων

--rls

false

PostgreSQL: ενεργοποιεί το Row-Level Security ανά tenant (άμυνα σε βάθος, προαιρετική)

--bearoff-ts <fichier>

προαιρετική βάση bearoff two-sided (.bd) που διευρύνει την ενσωματωμένη βάση TS-06-06 για την ανάλυση κούρσας του σημείου πρόσβασης EPC· ο δαίμονας δεν κατεβάζει ποτέ βάση από μόνος του — προσαρτήστε το αρχείο ως volume και ορίστε το εδώ

Οι περισσότερες επιλογές μπορούν επίσης να παρασχεθούν μέσω μεταβλητής περιβάλλοντος (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 αποκωδικοποιούν μια θέση χωρίς να την αποθηκεύουν: η positions.fromXGID ανακατασκευάζει μια θέση από μια συμβολοσειρά XGID και η positions.fromXGP από ένα αρχείο μεμονωμένης θέσης .xgp.

Η οικογένεια anki αποκτά έξι μεθόδους που επεκτείνουν τον προγραμματιστή διαστηματικής επανάληψης (FSRS): anki.reviewLog (καταγραφή κάθε επανάληψης — βαθμολογία και αποτέλεσμα FSRS — για στατιστικά διατήρησης και ένα πιστό ιστορικό), anki.forecast (προβολή του αριθμού καρτών που οφείλονται τις επόμενες ημέρες, συμπεριλαμβανομένων των καθυστερημένων καρτών), anki.suspendCard / anki.buryCard / anki.removeCard (αφαίρεση μιας κάρτας από την ουρά επανάληψης προσωρινά ή οριστικά) και anki.optimizeParams (προσαρμόζει το στοχευόμενο ποσοστό διατήρησης ενός deck προς το ποσοστό επιτυχίας που παρατηρείται στις επαναλήψεις του).

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).

Προειδοποίηση

Όπως και ο ίδιος ο δαίμονας, το κοντέινερ δεν εκτελεί καμία πιστοποίηση ταυτότητας: πρέπει να τοποθετείται πίσω από έναν reverse-proxy υπεύθυνο για την πιστοποίηση ταυτότητας και να μην εκτίθεται ποτέ απευθείας στο δημόσιο Διαδίκτυο.

8.3. Backend PostgreSQL και πολλαπλοί χρήστες

Για μια κοινόχρηστη ανάπτυξη, το blunderDB μπορεί να αποθηκεύει τα δεδομένα στο PostgreSQL αντί σε ένα αρχείο SQLite. Το backend επιλέγεται μέσω του --backend postgres και της συμβολοσειράς σύνδεσης --dsn. Το σχήμα δημιουργείται και μεταναστεύεται αυτόματα κατά την εκκίνηση.

Τα δεδομένα είναι διαχωρισμένα ανά tenant (μισθωτή): κάθε αίτημα φέρει ένα αναγνωριστικό scope (κεφαλίδα X-Tenant-ID, εξ ορισμού default), πράγμα που επιτρέπει σε πολλούς χρήστες να μοιράζονται το ίδιο instance χωρίς να βλέπουν τα δεδομένα των άλλων. Η επιλογή --rls ενεργοποιεί επιπλέον το Row-Level Security του PostgreSQL: εγκαθίστανται πολιτικές απομόνωσης ανά tenant και το app.tenant_id ορίζεται ανά σύνδεση. Πρόκειται για μια προαιρετική άμυνα σε βάθος, απενεργοποιημένη εξ ορισμού.

Όταν ένα tenant καταργείται, το POST /v1/tenant.purge διαγράφει οριστικά όλα τα δεδομένα του (θέσεις, αγώνες, συλλογές, ιστορικό κ.λπ.) για το τρέχον tenant (αυτό που φέρει το X-Tenant-ID), καθώς και την κατάσταση συνεδρίας του (τελευταία αναζήτηση, τελευταία θέση, ανοιχτές καρτέλες — τις λίγες γραμμές metadata με πρόθεμα αυτού του scope): η λειτουργία εκτελείται σε μία μοναδική συναλλαγή, είναι ιδεμποτική (κανένα σφάλμα κατά την εκκαθάριση ενός ήδη κενού tenant ή κατά την επανάληψη της κλήσης) και δεν επηρεάζει κανένα άλλο tenant ούτε την καθολική γραμμή έκδοσης σχήματος. Είναι διαθέσιμη μόνο με το backend PostgreSQL — επιστρέφει σφάλμα invalid σε ένα backend SQLite, το οποίο δεν έχει έννοια tenant.

8.4. Μετανάστευση μιας βάσης SQLite προς PostgreSQL

Το blunderdb migrate αντιγράφει μια βάση SQLite ενός χρήστη προς ένα backend PostgreSQL, υπό ένα επιλεγμένο scope tenant — είναι ο τρόπος για να « μεταφορτώσετε » μια βιβλιοθήκη γραφείου προς μια ανάπτυξη διακομιστή.

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.

Επιλογή

Προεπιλογή

Σημασία

--from <uri>

βάση SQLite πηγής (sqlite:///chemin ή μια απλή διαδρομή)

--to <dsn>

DSN PostgreSQL προορισμού (postgres://…)

--tenant-id <scope>

scope tenant προορισμού (υποχρεωτικό εκτός από --dry-run)

--dry-run

μετρά τι θα αντιγραφόταν χωρίς να γράψει τίποτα

--on-conflict <politique>

""

"" διακόπτει αν ο tenant έχει ήδη δεδομένα· το skip συγχωνεύει (αφαίρεση διπλότυπων θέσεων μέσω hash Zobrist)

Σημείωση

Δεν μεταναστεύονται (ακόμη) οι καταστάσεις της εφαρμογής: decks/κάρτες Anki, βιβλιοθήκη φίλτρων, ιστορικό αναζήτησης και εντολών, και μεταδεδομένα συνεδρίας. Η προτεραιότητα είναι η μετανάστευση της βιβλιοθήκης θέσεων και του ιστορικού αγώνων.

8.5. Ο γενικός dispatcher call

Συμπληρωματικά προς τις ιστορικές υποεντολές (Διεπαφή γραμμής εντολών (CLI)), το blunderdb call εκθέτει όλες τις λειτουργίες αποθήκευσης απευθείας, τοπικά. Περνά από τους ίδιους χειριστές με τον δαίμονα serve: η συμπεριφορά είναι επομένως πανομοιότυπη με το POST /v1/<famille>.<méthode>. Είναι χρήσιμο για το scripting και τις δοκιμές ολοκλήρωσης.

# 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 <chemin>

αρχείο SQLite (συντόμευση για --backend sqlite --dsn <chemin>)

--backend <type>

sqlite

sqlite ή postgres

--dsn <chaîne>

$BLUNDERDB_DSN

συμβολοσειρά σύνδεσης του backend

--scope <chaîne>

default

scope tenant (αποστέλλεται ως X-Tenant-ID)

--json <chaîne>

{}

σώμα του αιτήματος σε μορφή JSON

--json-file <chemin>

διαβάζει το σώμα του αιτήματος από ένα αρχείο

--list

εμφανίζει όλες τις μεθόδους <famille>.<méthode> και τερματίζει

Η απάντηση JSON (ή η ροή NDJSON για τα σημεία πρόσβασης *.list) γράφεται στην τυπική έξοδο. Σε περίπτωση σφάλματος, η διεργασία τερματίζεται με μη μηδενικό κωδικό και ο φάκελος {"error":{…}} εκτυπώνεται στην τυπική έξοδο ώστε να παραμένει αναλύσιμος (για παράδειγμα με το jq).