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 (άμυνα σε βάθος, προαιρετική)

Οι περισσότερες επιλογές μπορούν επίσης να παρασχεθούν μέσω μεταβλητής περιβάλλοντος (BLUNDERDB_BACKEND, BLUNDERDB_DSN, BLUNDERDB_ADDR, BLUNDERDB_LOG_LEVEL, BLUNDERDB_RLS).

8.2.1. Σημεία πρόσβασης

Η υπηρεσία εκθέτει σημεία πρόσβασης λειτουργίας, πάντα διαθέσιμα:

  • GET /healthz — ζωτικότητα (η διεργασία τρέχει)·

  • GET /readyz — διαθεσιμότητα (η αποθήκευση απαντά)·

  • GET /metrics — μετρικές Prometheus (αν το --metrics είναι ενεργό).

Η επιφάνεια λειτουργιών ακολουθεί το σχήμα POST /v1/<famille>.<méthode> (για παράδειγμα /v1/positions.save, /v1/matches.get). Οι οικογένειες καλύπτουν τις θέσεις, τις αναλύσεις, τους αγώνες, τα σχόλια, τις συλλογές, τα τουρνουά, τις κάρτες Anki, τα φίλτρα, τις συνεδρίες, την αναζήτηση, τα μεταδεδομένα, τα στατιστικά και την εισαγωγή. Τα σημεία πρόσβασης καταχώρισης επιστρέφουν μια ροή NDJSON (ένα αντικείμενο JSON ανά γραμμή). Ο διακομιστής τερματίζεται καθαρά με SIGINT / SIGTERM.

Δύο μέθοδοι της οικογένειας positions αποκωδικοποιούν μια θέση χωρίς να την αποθηκεύουν: η positions.fromXGID ανακατασκευάζει μια θέση από μια συμβολοσειρά XGID και η positions.fromXGP από ένα αρχείο μεμονωμένης θέσης .xgp.

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 ορίζεται ανά σύνδεση. Πρόκειται για μια προαιρετική άμυνα σε βάθος, απενεργοποιημένη εξ ορισμού.

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

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

Επιλογή

Προεπιλογή

Σημασία

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