release: v1.2.0 Production GA (single-node)
CI / test (push) Has been cancelled
CI / verify (push) Has been cancelled
Clients CI / build-server (push) Has been cancelled
Clients CI / test-python (push) Has been cancelled
Clients CI / test-javascript (push) Has been cancelled
Clients CI / test-nim (push) Has been cancelled
Clients CI / test-rust (push) Has been cancelled
CI / test (push) Has been cancelled
CI / verify (push) Has been cancelled
Clients CI / build-server (push) Has been cancelled
Clients CI / test-python (push) Has been cancelled
Clients CI / test-javascript (push) Has been cancelled
Clients CI / test-nim (push) Has been cancelled
Clients CI / test-rust (push) Has been cancelled
- known-limitations, deployment runbook, release checklist - prod compose requires JWT secret; BARADB_ENV=production fail-closed - scripts/backup-restore-drill.sh (backup → wipe → restore → verify) - version bump 1.2.0 (nimble, Dockerfile, health, CHANGELOG dated)
This commit is contained in:
+9
-1
@@ -2,7 +2,15 @@
|
|||||||
|
|
||||||
All notable changes to BaraDB are documented in this file.
|
All notable changes to BaraDB are documented in this file.
|
||||||
|
|
||||||
## [1.2.0] — Unreleased
|
## [1.2.0] — 2026-07-30
|
||||||
|
|
||||||
|
### Production GA (single-node)
|
||||||
|
|
||||||
|
- **Scope** — single-node production tier; Raft multi-node documented as experimental ([known-limitations](docs/en/known-limitations.md))
|
||||||
|
- **Prod compose** — `docker-compose.prod.yml` requires `BARADB_JWT_SECRET` and enables auth; `BARADB_ENV=production` fails closed without secret
|
||||||
|
- **Backup drill** — `scripts/backup-restore-drill.sh` (backup → wipe → restore → verify)
|
||||||
|
- **Runbook** — start/stop/backup/restore in [deployment](docs/en/deployment.md)
|
||||||
|
- **Release checklist** — [docs/en/release-checklist.md](docs/en/release-checklist.md)
|
||||||
|
|
||||||
### Raft cluster (C3a / C3b / ops)
|
### Raft cluster (C3a / C3b / ops)
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@ ARG VCS_REF
|
|||||||
|
|
||||||
LABEL maintainer="BaraDB Team"
|
LABEL maintainer="BaraDB Team"
|
||||||
LABEL description="BaraDB — Multimodal Database Engine"
|
LABEL description="BaraDB — Multimodal Database Engine"
|
||||||
LABEL version="1.1.6"
|
LABEL version="1.2.0"
|
||||||
|
|
||||||
# Инсталираме runtime зависимости
|
# Инсталираме runtime зависимости
|
||||||
# libpcre3 — нужна за Nim regex (зарежда се динамично)
|
# libpcre3 — нужна за Nim regex (зарежда се динамично)
|
||||||
|
|||||||
@@ -156,7 +156,7 @@
|
|||||||
| `PLAN_ID_GENERATORS.md` — AUTO_INCREMENT, Sequences, FK | ✅ Завършен |
|
| `PLAN_ID_GENERATORS.md` — AUTO_INCREMENT, Sequences, FK | ✅ Завършен |
|
||||||
| **Този план** — Сесии 10, 11, 12 | ✅ Завършен |
|
| **Този план** — Сесии 10, 11, 12 | ✅ Завършен |
|
||||||
| Raft C3a/C3b + DDL/forward/compact/metrics (2026-07-30) | ✅ Завършен на `main` — `docs/superpowers/specs/2026-07-30-raft-cluster-status.md` |
|
| Raft C3a/C3b + DDL/forward/compact/metrics (2026-07-30) | ✅ Завършен на `main` — `docs/superpowers/specs/2026-07-30-raft-cluster-status.md` |
|
||||||
| **Production GA v1.2.0** (single-node) | 📋 План — `docs/superpowers/plans/2026-07-30-production-ga.md` |
|
| **Production GA v1.2.0** (single-node) | ✅ `docs/superpowers/plans/2026-07-30-production-ga.md` |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1576,7 +1576,7 @@ features are still being refined:
|
|||||||
| LSM-Tree SSTable reads | ✅ Implemented | Full disk I/O with compaction, WAL, and bloom filters. |
|
| LSM-Tree SSTable reads | ✅ Implemented | Full disk I/O with compaction, WAL, and bloom filters. |
|
||||||
| HNSW vector search | ✅ Implemented | Hierarchical graph navigation with SIMD-optimized distance metrics. |
|
| HNSW vector search | ✅ Implemented | Hierarchical graph navigation with SIMD-optimized distance metrics. |
|
||||||
| TCP server execution | ✅ Implemented | Full binary wire protocol parsing and BaraQL query execution. |
|
| TCP server execution | ✅ Implemented | Full binary wire protocol parsing and BaraQL query execution. |
|
||||||
| Raft consensus | ✅ Cluster path | TCP election + failover; SQL DML/DDL via raft log; leader forwarding; safe log compact; `/metrics` + `/health` raft gauges. See `docs/en/distributed.md`. |
|
| Raft consensus | ⚡ Experimental cluster | TCP election + SQL/DDL via log; single-node is **Production GA**. See `docs/en/known-limitations.md`. |
|
||||||
| Graph / FTS / Columnar | ✅ Implemented | In-memory engines with serialization; FTS/vector/graph indexes persist across restarts. |
|
| Graph / FTS / Columnar | ✅ Implemented | In-memory engines with serialization; FTS/vector/graph indexes persist across restarts. |
|
||||||
| Query codegen | ✅ Implemented | IR plans compile to storage engine operations with optimization passes. |
|
| Query codegen | ✅ Implemented | IR plans compile to storage engine operations with optimization passes. |
|
||||||
|
|
||||||
@@ -1585,7 +1585,10 @@ reflects 100% completion across all major phases.
|
|||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
See [CHANGELOG.md](CHANGELOG.md) for full release history. Package version is **v1.1.8**. The **v1.2.0** line (Unreleased) adds core storage hardening, Unified Search Engine, **engine persistence** (FTS/HNSW/graphs/B-tree indexes across restart), **executor split**, and a full **Raft cluster path** (election, SQL/DDL replication, forwarding, log compact, metrics — see [docs/en/distributed.md](docs/en/distributed.md)).
|
See [CHANGELOG.md](CHANGELOG.md) for full release history. Package version is **v1.2.0**.
|
||||||
|
|
||||||
|
- **Production GA (single-node):** auth-on prod compose, backup/restore drill, runbook — [known-limitations](docs/en/known-limitations.md), [deployment](docs/en/deployment.md)
|
||||||
|
- **Raft multi-node:** experimental — [distributed.md](docs/en/distributed.md)
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
# Package
|
# Package
|
||||||
version = "1.1.8"
|
version = "1.2.0"
|
||||||
author = "BaraDB Team"
|
author = "BaraDB Team"
|
||||||
description = "BaraDB — Multimodal database written in Nim"
|
description = "BaraDB — Multimodal database written in Nim"
|
||||||
license = "BSD-3-Clause"
|
license = "BSD-3-Clause"
|
||||||
|
|||||||
+39
-42
@@ -1,82 +1,87 @@
|
|||||||
# BaraDB — Production Docker Compose
|
# BaraDB — Production Docker Compose (v1.2.0 GA)
|
||||||
# Usage: docker compose -f docker-compose.prod.yml up -d
|
|
||||||
#
|
#
|
||||||
# Препоръчителни стъпки преди production deployment:
|
# Usage:
|
||||||
# 1. Създайте TLS сертификати в ./certs/
|
# export BARADB_JWT_SECRET="$(openssl rand -hex 32)"
|
||||||
# 2. Задайте силен BARADB_JWT_SECRET
|
# docker compose -f docker-compose.prod.yml up -d --build
|
||||||
# 3. Настройте firewall правила за портовете
|
#
|
||||||
# 4. Конфигурирайте регулярни backups
|
# Required:
|
||||||
|
# BARADB_JWT_SECRET — strong secret (compose fails if unset)
|
||||||
|
#
|
||||||
|
# Ports (BARADB_PORT=9472):
|
||||||
|
# 9472 binary wire
|
||||||
|
# 9912 HTTP (= TCP + 440)
|
||||||
|
# 9913 WebSocket (= TCP + 441)
|
||||||
|
#
|
||||||
|
# Notes:
|
||||||
|
# - Auth is ON. Obtain a token via POST /auth before /query.
|
||||||
|
# - `deploy.resources` applies under Swarm; plain Compose ignores limits.
|
||||||
|
# - Raft is optional/experimental — not enabled here (single-node GA).
|
||||||
|
|
||||||
services:
|
services:
|
||||||
baradb:
|
baradb:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
image: baradb:latest
|
image: baradb:1.2.0
|
||||||
container_name: baradb
|
container_name: baradb
|
||||||
hostname: baradb
|
hostname: baradb
|
||||||
restart: always
|
restart: always
|
||||||
|
|
||||||
ports:
|
ports:
|
||||||
- "9472:9472" # Binary protocol
|
- "9472:9472" # Binary protocol
|
||||||
- "9912:9912" # HTTP/REST API
|
- "9912:9912" # HTTP REST (TCP+440)
|
||||||
- "9913:9913" # WebSocket
|
- "9913:9913" # WebSocket (TCP+441)
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
- baradb_data:/data
|
- baradb_data:/data
|
||||||
# TLS сертификати (read-only)
|
|
||||||
- ./certs:/certs:ro
|
- ./certs:/certs:ro
|
||||||
# Лог файлове на хоста
|
|
||||||
- ./logs:/var/log/baradb
|
- ./logs:/var/log/baradb
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
# Network
|
- BARADB_ENV=production
|
||||||
- BARADB_ADDRESS=0.0.0.0
|
- BARADB_ADDRESS=0.0.0.0
|
||||||
- BARADB_PORT=9472
|
- BARADB_PORT=9472
|
||||||
|
|
||||||
# Storage
|
|
||||||
- BARADB_DATA_DIR=/data
|
- BARADB_DATA_DIR=/data
|
||||||
- BARADB_MEMTABLE_SIZE_MB=256
|
- BARADB_MEMTABLE_SIZE_MB=256
|
||||||
- BARADB_CACHE_SIZE_MB=512
|
- BARADB_CACHE_SIZE_MB=512
|
||||||
|
|
||||||
# TLS (разкоментирайте когато имате сертификати)
|
# Security — fail closed without a real secret
|
||||||
|
- BARADB_AUTH_ENABLED=true
|
||||||
|
- BARADB_JWT_SECRET=${BARADB_JWT_SECRET:?Set BARADB_JWT_SECRET to a strong random value}
|
||||||
|
- BARADB_RATE_LIMIT_GLOBAL=10000
|
||||||
|
- BARADB_RATE_LIMIT_PER_CLIENT=1000
|
||||||
|
|
||||||
|
# TLS (uncomment when certs exist under ./certs)
|
||||||
# - BARADB_TLS_ENABLED=true
|
# - BARADB_TLS_ENABLED=true
|
||||||
# - BARADB_CERT_FILE=/certs/server.crt
|
# - BARADB_CERT_FILE=/certs/server.crt
|
||||||
# - BARADB_KEY_FILE=/certs/server.key
|
# - BARADB_KEY_FILE=/certs/server.key
|
||||||
|
|
||||||
# Security (ЗАДЪЛЖИТЕЛНО сменете в production!)
|
|
||||||
# - BARADB_AUTH_ENABLED=true
|
|
||||||
# - BARADB_JWT_SECRET=change-me-to-random-32-char-string
|
|
||||||
# - BARADB_RATE_LIMIT_GLOBAL=10000
|
|
||||||
# - BARADB_RATE_LIMIT_PER_CLIENT=1000
|
|
||||||
|
|
||||||
# Logging
|
|
||||||
- BARADB_LOG_LEVEL=warn
|
- BARADB_LOG_LEVEL=warn
|
||||||
- BARADB_LOG_FILE=/var/log/baradb/baradb.log
|
- BARADB_LOG_FILE=/var/log/baradb/baradb.log
|
||||||
- BARADB_LOG_FORMAT=json
|
- BARADB_LOG_FORMAT=json
|
||||||
|
|
||||||
# Performance
|
|
||||||
- BARADB_COMPACTION_INTERVAL_MS=30000
|
- BARADB_COMPACTION_INTERVAL_MS=30000
|
||||||
- BARADB_WAL_SYNC_INTERVAL_MS=10
|
# Match config.nim env names
|
||||||
|
- BARADB_WAL_SYNC_MODE=group
|
||||||
|
- BARADB_WAL_GROUP_EVERY=64
|
||||||
|
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "sh", "-c", "wget -qO- http://localhost:9912/health >/dev/null 2>&1"]
|
test: ["CMD", "sh", "-c", "wget -qO- http://127.0.0.1:9912/health >/dev/null 2>&1"]
|
||||||
interval: 15s
|
interval: 15s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 5
|
retries: 5
|
||||||
start_period: 30s
|
start_period: 30s
|
||||||
|
|
||||||
# Production resource limits
|
|
||||||
deploy:
|
deploy:
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
cpus: '4.0'
|
cpus: "4.0"
|
||||||
memory: 8G
|
memory: 8G
|
||||||
reservations:
|
reservations:
|
||||||
cpus: '1.0'
|
cpus: "1.0"
|
||||||
memory: 1G
|
memory: 1G
|
||||||
|
|
||||||
# Security hardening
|
|
||||||
security_opt:
|
security_opt:
|
||||||
- no-new-privileges:true
|
- no-new-privileges:true
|
||||||
read_only: true
|
read_only: true
|
||||||
@@ -91,19 +96,19 @@ services:
|
|||||||
options:
|
options:
|
||||||
max-size: "100m"
|
max-size: "100m"
|
||||||
max-file: "5"
|
max-file: "5"
|
||||||
labels: "service_name"
|
|
||||||
|
|
||||||
# Опционален: Backup cron job
|
# Optional offline-style backup sidecar (shares data volume read-only)
|
||||||
backup:
|
backup:
|
||||||
image: baradb:latest
|
image: baradb:1.2.0
|
||||||
container_name: baradb-backup
|
container_name: baradb-backup
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
profiles: ["backup"]
|
||||||
command: >
|
command: >
|
||||||
sh -c '
|
sh -c '
|
||||||
while true; do
|
while true; do
|
||||||
sleep 86400;
|
sleep 86400;
|
||||||
/app/backup backup --all-databases --data-root=/data/databases --output=/backups/baradb_$$(date +%Y%m%d_%H%M%S).tar.gz --level=6;
|
/app/backup backup --all-databases --data-root=/data/databases --output=/backups/baradb_$$(date +%Y%m%d_%H%M%S).tar.gz --level=6 || true;
|
||||||
/app/backup cleanup --data-root=/data/databases --keep=7;
|
/app/backup cleanup --data-root=/data/databases --keep=7 || true;
|
||||||
done
|
done
|
||||||
'
|
'
|
||||||
volumes:
|
volumes:
|
||||||
@@ -111,11 +116,6 @@ services:
|
|||||||
- ./backups:/backups
|
- ./backups:/backups
|
||||||
networks:
|
networks:
|
||||||
- baradb_net
|
- baradb_net
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpus: '0.5'
|
|
||||||
memory: 512M
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
baradb_data:
|
baradb_data:
|
||||||
@@ -124,6 +124,3 @@ volumes:
|
|||||||
networks:
|
networks:
|
||||||
baradb_net:
|
baradb_net:
|
||||||
driver: bridge
|
driver: bridge
|
||||||
ipam:
|
|
||||||
config:
|
|
||||||
- subnet: 172.28.0.0/16
|
|
||||||
|
|||||||
+20
-235
@@ -1,250 +1,35 @@
|
|||||||
# Ръководство за Внедряване (Deployment)
|
# Deployment Guide (кратко)
|
||||||
|
|
||||||
## Docker
|
**Production GA v1.2.0** = **single-node**. Виж [known-limitations](known-limitations.md).
|
||||||
|
Пълен runbook: [en/deployment.md](../en/deployment.md).
|
||||||
|
|
||||||
За пълно ръководство за Docker deployment вижте [Docker Guide](docker.md).
|
## Портове
|
||||||
|
|
||||||
### Бърз старт
|
| Услуга | Порт |
|
||||||
|
|--------|------|
|
||||||
|
| Wire | `BARADB_PORT` (9472) |
|
||||||
|
| HTTP | `BARADB_PORT + 440` (9912) |
|
||||||
|
| WebSocket | `BARADB_PORT + 441` (9913) |
|
||||||
|
|
||||||
|
Няма `BARADB_HTTP_PORT`.
|
||||||
|
|
||||||
|
## Production Docker
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker build -t baradb:latest .
|
export BARADB_JWT_SECRET="$(openssl rand -hex 32)"
|
||||||
docker compose up -d
|
docker compose -f docker-compose.prod.yml up -d --build
|
||||||
```
|
```
|
||||||
|
|
||||||
### Docker Compose файлове
|
Auth е включен; без secret compose **спира**.
|
||||||
|
|
||||||
| Файл | Назначение |
|
## Backup / restore drill
|
||||||
|------|-----------|
|
|
||||||
| `docker-compose.yml` | Development |
|
|
||||||
| `docker-compose.prod.yml` | Production |
|
|
||||||
| `docker-compose.override.yml` | Dev override (автоматично) |
|
|
||||||
| `docker-compose.test.yml` | Тестова среда |
|
|
||||||
|
|
||||||
### Production
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose -f docker-compose.prod.yml up -d
|
./scripts/backup-restore-drill.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
### Docker Swarm
|
## Health
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker stack deploy -c docker-compose.prod.yml baradb
|
curl -s http://127.0.0.1:9912/health
|
||||||
```
|
|
||||||
|
|
||||||
## systemd Услуга
|
|
||||||
|
|
||||||
Създайте `/etc/systemd/system/baradb.service`:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[Unit]
|
|
||||||
Description=BaraDB Multimodal Database
|
|
||||||
After=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
User=baradb
|
|
||||||
Group=baradb
|
|
||||||
WorkingDirectory=/var/lib/baradb
|
|
||||||
ExecStart=/usr/local/bin/baradadb
|
|
||||||
Restart=always
|
|
||||||
RestartSec=5
|
|
||||||
|
|
||||||
Environment=BARADB_PORT=9472
|
|
||||||
Environment=BARADB_HTTP_PORT=9470
|
|
||||||
Environment=BARADB_DATA_DIR=/var/lib/baradb/data
|
|
||||||
Environment=BARADB_LOG_LEVEL=info
|
|
||||||
|
|
||||||
# Подсилване на сигурността
|
|
||||||
NoNewPrivileges=true
|
|
||||||
ProtectSystem=strict
|
|
||||||
ProtectHome=true
|
|
||||||
ReadWritePaths=/var/lib/baradb/data
|
|
||||||
ProtectKernelTunables=true
|
|
||||||
ProtectKernelModules=true
|
|
||||||
ProtectControlGroups=true
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
```
|
|
||||||
|
|
||||||
Активиране и стартиране:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo useradd -r -s /bin/false baradb
|
|
||||||
sudo mkdir -p /var/lib/baradb/data
|
|
||||||
sudo chown -R baradb:baradb /var/lib/baradb
|
|
||||||
sudo cp build/baradadb /usr/local/bin/
|
|
||||||
sudo systemctl daemon-reload
|
|
||||||
sudo systemctl enable --now baradb
|
|
||||||
```
|
|
||||||
|
|
||||||
## Kubernetes
|
|
||||||
|
|
||||||
### StatefulSet
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: StatefulSet
|
|
||||||
metadata:
|
|
||||||
name: baradb
|
|
||||||
spec:
|
|
||||||
serviceName: baradb
|
|
||||||
replicas: 3
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: baradb
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: baradb
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: baradb
|
|
||||||
image: baradb:latest
|
|
||||||
ports:
|
|
||||||
- containerPort: 9472
|
|
||||||
name: binary
|
|
||||||
- containerPort: 9470
|
|
||||||
name: http
|
|
||||||
- containerPort: 9471
|
|
||||||
name: websocket
|
|
||||||
env:
|
|
||||||
- name: BARADB_DATA_DIR
|
|
||||||
value: /data
|
|
||||||
- name: BARADB_RAFT_NODE_ID
|
|
||||||
valueFrom:
|
|
||||||
fieldRef:
|
|
||||||
fieldPath: metadata.name
|
|
||||||
volumeMounts:
|
|
||||||
- name: data
|
|
||||||
mountPath: /data
|
|
||||||
volumeClaimTemplates:
|
|
||||||
- metadata:
|
|
||||||
name: data
|
|
||||||
spec:
|
|
||||||
accessModes: ["ReadWriteOnce"]
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
storage: 100Gi
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: baradb
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
app: baradb
|
|
||||||
ports:
|
|
||||||
- port: 9472
|
|
||||||
name: binary
|
|
||||||
- port: 9470
|
|
||||||
name: http
|
|
||||||
- port: 9471
|
|
||||||
name: websocket
|
|
||||||
clusterIP: None
|
|
||||||
```
|
|
||||||
|
|
||||||
## Reverse Proxy (nginx)
|
|
||||||
|
|
||||||
```nginx
|
|
||||||
upstream baradb_http {
|
|
||||||
server 127.0.0.1:9470;
|
|
||||||
}
|
|
||||||
|
|
||||||
upstream baradb_ws {
|
|
||||||
server 127.0.0.1:9471;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
server_name db.example.com;
|
|
||||||
return 301 https://$server_name$request_uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 443 ssl http2;
|
|
||||||
server_name db.example.com;
|
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/db.example.com/fullchain.pem;
|
|
||||||
ssl_certificate_key /etc/letsencrypt/live/db.example.com/privkey.pem;
|
|
||||||
|
|
||||||
location /api/ {
|
|
||||||
proxy_pass http://baradb_http/;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /ws/ {
|
|
||||||
proxy_pass http://baradb_ws/;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection "upgrade";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Висока Достъпност (High Availability)
|
|
||||||
|
|
||||||
### 3-Възел Raft Клъстер
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Възел 1
|
|
||||||
BARADB_RAFT_NODE_ID=node1 \
|
|
||||||
BARADB_RAFT_PEERS=node2:9001,node3:9001 \
|
|
||||||
./build/baradadb
|
|
||||||
|
|
||||||
# Възел 2
|
|
||||||
BARADB_RAFT_NODE_ID=node2 \
|
|
||||||
BARADB_RAFT_PEERS=node1:9001,node3:9001 \
|
|
||||||
./build/baradadb
|
|
||||||
|
|
||||||
# Възел 3
|
|
||||||
BARADB_RAFT_NODE_ID=node3 \
|
|
||||||
BARADB_RAFT_PEERS=node1:9001,node2:9001 \
|
|
||||||
./build/baradadb
|
|
||||||
```
|
|
||||||
|
|
||||||
## Облачно Внедряване
|
|
||||||
|
|
||||||
### AWS EC2
|
|
||||||
|
|
||||||
Препоръчителна инстанция: `m6i.2xlarge` (8 vCPU, 32 GB RAM)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# User data скрипт
|
|
||||||
#!/bin/bash
|
|
||||||
apt-get update
|
|
||||||
apt-get install -y nim
|
|
||||||
wget https://github.com/katehonz/barabaDB/releases/latest/download/baradadb-linux-amd64
|
|
||||||
chmod +x baradadb-linux-amd64
|
|
||||||
mv baradadb-linux-amd64 /usr/local/bin/baradadb
|
|
||||||
|
|
||||||
mkdir -p /data/baradb
|
|
||||||
cat > /etc/systemd/system/baradb.service << 'EOF'
|
|
||||||
[Unit]
|
|
||||||
Description=BaraDB
|
|
||||||
After=network.target
|
|
||||||
[Service]
|
|
||||||
ExecStart=/usr/local/bin/baradadb
|
|
||||||
Environment=BARADB_DATA_DIR=/data/baradb
|
|
||||||
Restart=always
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
|
|
||||||
systemctl daemon-reload
|
|
||||||
systemctl enable --now baradb
|
|
||||||
```
|
|
||||||
|
|
||||||
### GCP Cloud Run (само HTTP)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
gcloud run deploy baradb \
|
|
||||||
--image gcr.io/PROJECT/baradb \
|
|
||||||
--port 9470 \
|
|
||||||
--memory 4Gi \
|
|
||||||
--cpu 2 \
|
|
||||||
--max-instances 10
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# Известни ограничения — v1.2.0 Production GA
|
||||||
|
|
||||||
|
| Ниво | Значение |
|
||||||
|
|------|----------|
|
||||||
|
| **Supported (GA)** | Документирано, тествано, подходящо за prod в обхвата |
|
||||||
|
| **Experimental** | Работи в тестове/demo; не е HA SLA |
|
||||||
|
| **Not supported** | Извън обхват |
|
||||||
|
|
||||||
|
## Матрица
|
||||||
|
|
||||||
|
| Област | GA (v1.2.0) | Experimental / по-късно |
|
||||||
|
|--------|-------------|-------------------------|
|
||||||
|
| Single-node SQL + LSM | **Supported** | — |
|
||||||
|
| Schema / FTS / HNSW / graphs persist | **Supported** | — |
|
||||||
|
| Auth + JWT (когато е конфигуриран) | **Supported** | — |
|
||||||
|
| Backup / restore | **Supported** | — |
|
||||||
|
| Multi-DB (без Raft) | **Supported** | — |
|
||||||
|
| Raft 3-node + SQL/DDL | **Experimental** | InstallSnapshot, membership |
|
||||||
|
| Raft multi-DB | **Not supported** | само `default` |
|
||||||
|
| Follower linearizable reads | **Not supported** | best-effort след apply |
|
||||||
|
| ORC multi-thread shared LSM | **Not supported** | ARC по подразбиране |
|
||||||
|
|
||||||
|
## GA (single-node)
|
||||||
|
|
||||||
|
Crash recovery с WAL, schema/index persist, `/health` + `/metrics`, offline backup/restore.
|
||||||
|
|
||||||
|
## Raft
|
||||||
|
|
||||||
|
Виж [distributed.md](distributed.md). Staging/ops, **не** v1.2.0 HA продукт.
|
||||||
|
|
||||||
|
## Виж също
|
||||||
|
|
||||||
|
- [Deployment](deployment.md) · [Backup](backup.md) · [en limitations](../en/known-limitations.md)
|
||||||
+147
-164
@@ -1,39 +1,145 @@
|
|||||||
# Deployment Guide
|
# Deployment Guide
|
||||||
|
|
||||||
|
**Production GA (v1.2.0)** is **single-node**. See [known limitations](known-limitations.md).
|
||||||
|
Raft multi-node is [documented](distributed.md) as **experimental**.
|
||||||
|
|
||||||
|
## Ports
|
||||||
|
|
||||||
|
| Service | Port | Notes |
|
||||||
|
|---------|------|--------|
|
||||||
|
| Binary wire | `BARADB_PORT` (default 9472) | Clients |
|
||||||
|
| HTTP REST | `BARADB_PORT + 440` (9912) | `/health`, `/query`, `/metrics` |
|
||||||
|
| WebSocket | `BARADB_PORT + 441` (9913) | |
|
||||||
|
| Raft | `BARADB_RAFT_PORT` | Experimental cluster only |
|
||||||
|
|
||||||
|
There is **no** `BARADB_HTTP_PORT` — HTTP is always TCP+440.
|
||||||
|
|
||||||
## Docker
|
## Docker
|
||||||
|
|
||||||
За пълно ръководство за Docker deployment вижте [Docker Guide](docker.md).
|
See also [Docker Guide](docker.md).
|
||||||
|
|
||||||
### Бърз старт
|
### Development
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker build -t baradb:latest .
|
docker build -t baradb:latest .
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
### Docker Compose файлове
|
### Production (GA)
|
||||||
|
|
||||||
| Файл | Назначение |
|
```bash
|
||||||
|------|-----------|
|
export BARADB_JWT_SECRET="$(openssl rand -hex 32)"
|
||||||
|
docker compose -f docker-compose.prod.yml up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
- Auth is **on**; compose **fails** if `BARADB_JWT_SECRET` is unset.
|
||||||
|
- Binary sets `BARADB_ENV=production` → process refuses empty/placeholder secrets.
|
||||||
|
- Image tag: `baradb:1.2.0`.
|
||||||
|
|
||||||
|
Optional backup sidecar:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.prod.yml --profile backup up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
| Compose file | Role |
|
||||||
|
|--------------|------|
|
||||||
| `docker-compose.yml` | Development |
|
| `docker-compose.yml` | Development |
|
||||||
| `docker-compose.prod.yml` | Production |
|
| `docker-compose.prod.yml` | Production GA |
|
||||||
| `docker-compose.override.yml` | Dev override (автоматично) |
|
| `docker-compose.override.yml` | Local override |
|
||||||
|
|
||||||
### Production
|
> Note: `deploy.resources` limits apply under Docker Swarm; plain Compose may ignore them.
|
||||||
|
|
||||||
|
## Production runbook
|
||||||
|
|
||||||
|
### Start (binary)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose -f docker-compose.prod.yml up -d
|
export BARADB_ENV=production
|
||||||
|
export BARADB_AUTH_ENABLED=true
|
||||||
|
export BARADB_JWT_SECRET="$(openssl rand -hex 32)" # store securely
|
||||||
|
export BARADB_PORT=9472
|
||||||
|
export BARADB_DATA_DIR=/var/lib/baradb/data
|
||||||
|
export BARADB_LOG_LEVEL=warn
|
||||||
|
export BARADB_LOG_FILE=/var/log/baradb/baradb.log
|
||||||
|
./build/baradadb
|
||||||
```
|
```
|
||||||
|
|
||||||
### Docker Swarm
|
### Stop
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker stack deploy -c docker-compose.prod.yml baradb
|
# systemd
|
||||||
|
sudo systemctl stop baradb
|
||||||
|
# docker
|
||||||
|
docker compose -f docker-compose.prod.yml down
|
||||||
|
# foreground: Ctrl+C / SIGTERM
|
||||||
```
|
```
|
||||||
|
|
||||||
## systemd Service
|
### Health / metrics
|
||||||
|
|
||||||
Create `/etc/systemd/system/baradb.service`:
|
```bash
|
||||||
|
curl -s http://127.0.0.1:9912/health
|
||||||
|
curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1:9912/metrics
|
||||||
|
```
|
||||||
|
|
||||||
|
### Auth token (prod)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s -X POST http://127.0.0.1:9912/auth \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
-d "{\"username\":\"admin\",\"password\":\"$BARADB_JWT_SECRET\"}"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backup (server stopped or offline-consistent)
|
||||||
|
|
||||||
|
Preferred offline / all-databases:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./build/backup backup --all-databases \
|
||||||
|
--data-root=/var/lib/baradb/data/databases \
|
||||||
|
--output=/backups/baradb_$(date +%Y%m%d_%H%M%S).tar.gz
|
||||||
|
```
|
||||||
|
|
||||||
|
Copy archives off-host. Details: [backup.md](backup.md).
|
||||||
|
|
||||||
|
### Restore
|
||||||
|
|
||||||
|
1. **Stop** BaraDB.
|
||||||
|
2. Move aside or empty the data root (keep a copy of the broken dir).
|
||||||
|
3. Restore:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./build/backup restore --input=/backups/baradb_YYYYMMDD.tar.gz \
|
||||||
|
--all-databases --data-root=/var/lib/baradb/data/databases --force
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Start BaraDB; verify with a known query.
|
||||||
|
|
||||||
|
### Automated drill
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nim c -o:build/baradadb src/baradadb.nim
|
||||||
|
nim c -o:build/backup src/barabadb/core/backup.nim
|
||||||
|
./scripts/backup-restore-drill.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Logs
|
||||||
|
|
||||||
|
- File: `BARADB_LOG_FILE` (prod compose: `./logs` → `/var/log/baradb`)
|
||||||
|
- Docker: `docker logs baradb`
|
||||||
|
|
||||||
|
### Data layout
|
||||||
|
|
||||||
|
```
|
||||||
|
$BARADB_DATA_DIR/
|
||||||
|
databases/
|
||||||
|
default/ # LSM + WAL + schema keys
|
||||||
|
raft/ # only if raft enabled
|
||||||
|
```
|
||||||
|
|
||||||
|
## systemd
|
||||||
|
|
||||||
|
`/etc/systemd/system/baradb.service`:
|
||||||
|
|
||||||
```ini
|
```ini
|
||||||
[Unit]
|
[Unit]
|
||||||
@@ -49,16 +155,18 @@ ExecStart=/usr/local/bin/baradadb
|
|||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
|
|
||||||
|
Environment=BARADB_ENV=production
|
||||||
Environment=BARADB_PORT=9472
|
Environment=BARADB_PORT=9472
|
||||||
Environment=BARADB_HTTP_PORT=9470
|
|
||||||
Environment=BARADB_DATA_DIR=/var/lib/baradb/data
|
Environment=BARADB_DATA_DIR=/var/lib/baradb/data
|
||||||
Environment=BARADB_LOG_LEVEL=info
|
Environment=BARADB_LOG_LEVEL=warn
|
||||||
|
Environment=BARADB_AUTH_ENABLED=true
|
||||||
|
# Environment=BARADB_JWT_SECRET= # use EnvironmentFile
|
||||||
|
EnvironmentFile=-/etc/baradb/baradb.env
|
||||||
|
|
||||||
# Security hardening
|
|
||||||
NoNewPrivileges=true
|
NoNewPrivileges=true
|
||||||
ProtectSystem=strict
|
ProtectSystem=strict
|
||||||
ProtectHome=true
|
ProtectHome=true
|
||||||
ReadWritePaths=/var/lib/baradb/data
|
ReadWritePaths=/var/lib/baradb/data /var/log/baradb
|
||||||
ProtectKernelTunables=true
|
ProtectKernelTunables=true
|
||||||
ProtectKernelModules=true
|
ProtectKernelModules=true
|
||||||
ProtectControlGroups=true
|
ProtectControlGroups=true
|
||||||
@@ -67,114 +175,47 @@ ProtectControlGroups=true
|
|||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
```
|
```
|
||||||
|
|
||||||
Enable and start:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo useradd -r -s /bin/false baradb
|
sudo useradd -r -s /bin/false baradb
|
||||||
sudo mkdir -p /var/lib/baradb/data
|
sudo mkdir -p /var/lib/baradb/data /var/log/baradb /etc/baradb
|
||||||
sudo chown -R baradb:baradb /var/lib/baradb
|
# put BARADB_JWT_SECRET=... in /etc/baradb/baradb.env (mode 600)
|
||||||
sudo cp build/baradadb /usr/local/bin/
|
|
||||||
sudo systemctl daemon-reload
|
sudo systemctl daemon-reload
|
||||||
sudo systemctl enable --now baradb
|
sudo systemctl enable --now baradb
|
||||||
```
|
```
|
||||||
|
|
||||||
## Kubernetes
|
## High Availability (experimental)
|
||||||
|
|
||||||
### StatefulSet
|
Raft multi-node is **not** the v1.2.0 GA tier. See [distributed.md](distributed.md)
|
||||||
|
and [known-limitations](known-limitations.md). Use `id@host:port` peer format:
|
||||||
|
|
||||||
```yaml
|
```bash
|
||||||
apiVersion: apps/v1
|
export BARADB_RAFT_ENABLED=true
|
||||||
kind: StatefulSet
|
export BARADB_RAFT_NODE_ID=n1
|
||||||
metadata:
|
export BARADB_RAFT_PORT=46101
|
||||||
name: baradb
|
export BARADB_RAFT_PEERS=n1@127.0.0.1:46101,n2@127.0.0.1:46102,n3@127.0.0.1:46103
|
||||||
spec:
|
export BARADB_RAFT_CLIENT_PEERS=n1@127.0.0.1:46010,n2@127.0.0.1:46020,n3@127.0.0.1:46030
|
||||||
serviceName: baradb
|
|
||||||
replicas: 3
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: baradb
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: baradb
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: baradb
|
|
||||||
image: baradb:latest
|
|
||||||
ports:
|
|
||||||
- containerPort: 9472
|
|
||||||
name: binary
|
|
||||||
- containerPort: 9470
|
|
||||||
name: http
|
|
||||||
- containerPort: 9471
|
|
||||||
name: websocket
|
|
||||||
env:
|
|
||||||
- name: BARADB_DATA_DIR
|
|
||||||
value: /data
|
|
||||||
- name: BARADB_RAFT_NODE_ID
|
|
||||||
valueFrom:
|
|
||||||
fieldRef:
|
|
||||||
fieldPath: metadata.name
|
|
||||||
volumeMounts:
|
|
||||||
- name: data
|
|
||||||
mountPath: /data
|
|
||||||
volumeClaimTemplates:
|
|
||||||
- metadata:
|
|
||||||
name: data
|
|
||||||
spec:
|
|
||||||
accessModes: ["ReadWriteOnce"]
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
storage: 100Gi
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: baradb
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
app: baradb
|
|
||||||
ports:
|
|
||||||
- port: 9472
|
|
||||||
name: binary
|
|
||||||
- port: 9470
|
|
||||||
name: http
|
|
||||||
- port: 9471
|
|
||||||
name: websocket
|
|
||||||
clusterIP: None
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Reverse Proxy (nginx)
|
## Reverse proxy (nginx)
|
||||||
|
|
||||||
|
Proxy to **HTTP = TCP+440** (9912 if TCP is 9472):
|
||||||
|
|
||||||
```nginx
|
```nginx
|
||||||
upstream baradb_http {
|
upstream baradb_http {
|
||||||
server 127.0.0.1:9470;
|
server 127.0.0.1:9912;
|
||||||
}
|
}
|
||||||
|
|
||||||
upstream baradb_ws {
|
upstream baradb_ws {
|
||||||
server 127.0.0.1:9471;
|
server 127.0.0.1:9913;
|
||||||
}
|
}
|
||||||
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
server_name db.example.com;
|
|
||||||
return 301 https://$server_name$request_uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen 443 ssl http2;
|
listen 443 ssl http2;
|
||||||
server_name db.example.com;
|
server_name db.example.com;
|
||||||
|
location / {
|
||||||
ssl_certificate /etc/letsencrypt/live/db.example.com/fullchain.pem;
|
proxy_pass http://baradb_http;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/db.example.com/privkey.pem;
|
|
||||||
|
|
||||||
location /api/ {
|
|
||||||
proxy_pass http://baradb_http/;
|
|
||||||
proxy_http_version 1.1;
|
proxy_http_version 1.1;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
location /ws/ {
|
location /ws/ {
|
||||||
proxy_pass http://baradb_ws/;
|
proxy_pass http://baradb_ws/;
|
||||||
proxy_http_version 1.1;
|
proxy_http_version 1.1;
|
||||||
@@ -184,66 +225,8 @@ server {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## High Availability
|
## See also
|
||||||
|
|
||||||
### 3-Node Raft Cluster
|
- [Known limitations](known-limitations.md)
|
||||||
|
- [Release checklist](release-checklist.md)
|
||||||
```bash
|
- [Backup](backup.md) · [Monitoring](monitoring.md) · [Distributed / Raft](distributed.md)
|
||||||
# Node 1
|
|
||||||
BARADB_RAFT_NODE_ID=node1 \
|
|
||||||
BARADB_RAFT_PEERS=node2:9001,node3:9001 \
|
|
||||||
./build/baradadb
|
|
||||||
|
|
||||||
# Node 2
|
|
||||||
BARADB_RAFT_NODE_ID=node2 \
|
|
||||||
BARADB_RAFT_PEERS=node1:9001,node3:9001 \
|
|
||||||
./build/baradadb
|
|
||||||
|
|
||||||
# Node 3
|
|
||||||
BARADB_RAFT_NODE_ID=node3 \
|
|
||||||
BARADB_RAFT_PEERS=node1:9001,node2:9001 \
|
|
||||||
./build/baradadb
|
|
||||||
```
|
|
||||||
|
|
||||||
## Cloud Deployment
|
|
||||||
|
|
||||||
### AWS EC2
|
|
||||||
|
|
||||||
Recommended instance: `m6i.2xlarge` (8 vCPU, 32 GB RAM)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# User data script
|
|
||||||
#!/bin/bash
|
|
||||||
apt-get update
|
|
||||||
apt-get install -y nim
|
|
||||||
wget https://github.com/katehonz/barabaDB/releases/latest/download/baradadb-linux-amd64
|
|
||||||
chmod +x baradadb-linux-amd64
|
|
||||||
mv baradadb-linux-amd64 /usr/local/bin/baradadb
|
|
||||||
|
|
||||||
mkdir -p /data/baradb
|
|
||||||
cat > /etc/systemd/system/baradb.service << 'EOF'
|
|
||||||
[Unit]
|
|
||||||
Description=BaraDB
|
|
||||||
After=network.target
|
|
||||||
[Service]
|
|
||||||
ExecStart=/usr/local/bin/baradadb
|
|
||||||
Environment=BARADB_DATA_DIR=/data/baradb
|
|
||||||
Restart=always
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
|
|
||||||
systemctl daemon-reload
|
|
||||||
systemctl enable --now baradb
|
|
||||||
```
|
|
||||||
|
|
||||||
### GCP Cloud Run (HTTP only)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
gcloud run deploy baradb \
|
|
||||||
--image gcr.io/PROJECT/baradb \
|
|
||||||
--port 9470 \
|
|
||||||
--memory 4Gi \
|
|
||||||
--cpu 2 \
|
|
||||||
--max-instances 10
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ BaraDB supports distributed deployment with Raft consensus, sharding, and replic
|
|||||||
> ⚠️ **Multi-Database Limitation**
|
> ⚠️ **Multi-Database Limitation**
|
||||||
> The distributed modules (Raft, sharding, and replication) are currently wired to the **`default`** database only. If you use multiple databases (`CREATE DATABASE`, `USE DATABASE`), distributed features do not yet span across them. Each database would need its own cluster setup.
|
> The distributed modules (Raft, sharding, and replication) are currently wired to the **`default`** database only. If you use multiple databases (`CREATE DATABASE`, `USE DATABASE`), distributed features do not yet span across them. Each database would need its own cluster setup.
|
||||||
|
|
||||||
> **Status (2026-07-30):** Raft C3a (network election), C3b (SQL writes), DDL replication, leader forwarding, log compaction, and metrics are **shipped on `main`**. Design/history: `docs/superpowers/specs/2026-07-30-raft-cluster-status.md`.
|
> **Status (2026-07-30):** Raft C3a/C3b + DDL/forward/compact/metrics are **shipped**. Multi-node Raft is **experimental** for v1.2.0 GA (single-node is the production tier). See [known-limitations](known-limitations.md) and `docs/superpowers/specs/2026-07-30-raft-cluster-status.md`.
|
||||||
|
|
||||||
## Raft Consensus
|
## Raft Consensus
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
# Known Limitations — v1.2.0 Production GA
|
||||||
|
|
||||||
|
This page defines **what BaraDB promises** in the v1.2.0 production cut.
|
||||||
|
|
||||||
|
| Tier | Meaning |
|
||||||
|
|------|---------|
|
||||||
|
| **Supported (GA)** | Documented, tested, appropriate for production apps that fit the scope |
|
||||||
|
| **Experimental** | Works in tests/ops demos; not a reliability SLA target |
|
||||||
|
| **Not supported** | Out of scope; may fail or corrupt assumptions |
|
||||||
|
|
||||||
|
## Support matrix
|
||||||
|
|
||||||
|
| Area | GA (v1.2.0) | Experimental / later |
|
||||||
|
|------|-------------|----------------------|
|
||||||
|
| Single-node SQL + LSM storage | **Supported** | — |
|
||||||
|
| Schema persistence (tables, indexes) | **Supported** | — |
|
||||||
|
| FTS / HNSW / graphs across restart | **Supported** | — |
|
||||||
|
| Auth + JWT (when configured) | **Supported** | — |
|
||||||
|
| Backup / restore (offline, all-databases) | **Supported** | — |
|
||||||
|
| Multi-database (non-Raft) | **Supported** | — |
|
||||||
|
| Raft 3-node election + SQL/DDL | **Experimental** | InstallSnapshot SM payload, membership |
|
||||||
|
| Raft multi-database | **Not supported** | only `default` |
|
||||||
|
| Leader write forwarding | **Experimental** | needs `BARADB_RAFT_CLIENT_PEERS` |
|
||||||
|
| Follower linearizable reads | **Not supported** | best-effort after apply |
|
||||||
|
| ORC multi-threaded shared LSM | **Not supported** | default is ARC (`nim.cfg`) |
|
||||||
|
| Zero-downtime rolling upgrade | **Not supported** | stop → backup → upgrade |
|
||||||
|
| Postgres wire protocol | **Not supported** | Bara wire + HTTP |
|
||||||
|
|
||||||
|
## Single-node GA (what you can rely on)
|
||||||
|
|
||||||
|
- Process crash + WAL recovery for the default durability settings
|
||||||
|
- CREATE TABLE / indexes that survive restart (see engine-persistence work)
|
||||||
|
- HTTP `/health` and `/metrics` for process liveness
|
||||||
|
- Offline backup of `data/databases` and restore onto an empty data root
|
||||||
|
|
||||||
|
## Raft (experimental ops)
|
||||||
|
|
||||||
|
Documented in [distributed.md](distributed.md). Suitable for learning and careful staging; **not** the v1.2.0 HA product tier.
|
||||||
|
|
||||||
|
- SQL DML/DDL on **`default` only**
|
||||||
|
- Safe log prefix compact (not full InstallSnapshot)
|
||||||
|
- Failover proven in process e2e tests
|
||||||
|
|
||||||
|
## Operational requirements
|
||||||
|
|
||||||
|
- Set a strong `BARADB_JWT_SECRET` and `BARADB_AUTH_ENABLED=true` in production (see prod compose)
|
||||||
|
- Test restores regularly (`scripts/backup-restore-drill.sh`)
|
||||||
|
- Do not share one data directory between two running processes
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
- [Deployment / runbook](deployment.md)
|
||||||
|
- [Backup](backup.md)
|
||||||
|
- [Raft cluster status](../superpowers/specs/2026-07-30-raft-cluster-status.md)
|
||||||
|
- [Production GA plan](../superpowers/plans/2026-07-30-production-ga.md)
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
# Release checklist — v1.2.0 Production GA
|
||||||
|
|
||||||
|
Use before tagging and publishing artifacts.
|
||||||
|
|
||||||
|
## Pre-flight
|
||||||
|
|
||||||
|
- [ ] Working tree clean on `main`
|
||||||
|
- [ ] [Known limitations](known-limitations.md) accurate
|
||||||
|
- [ ] `CHANGELOG.md` has dated `## [1.2.0]` (not Unreleased for shipped items)
|
||||||
|
- [ ] `baradadb.nimble` version `1.2.0`
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nim c -o:build/baradadb src/baradadb.nim
|
||||||
|
nim c -o:build/backup src/barabadb/core/backup.nim
|
||||||
|
|
||||||
|
nim c -d:ssl --threads:on --path:src -r tests/test_all.nim
|
||||||
|
nim c -d:ssl --threads:on --path:src -r tests/bugfix_test.nim
|
||||||
|
nim c -d:ssl --threads:on --path:src -r tests/test_schema_persist.nim
|
||||||
|
|
||||||
|
# Ops drill (twice)
|
||||||
|
./scripts/backup-restore-drill.sh
|
||||||
|
DRILL_PORT=19482 ./scripts/backup-restore-drill.sh
|
||||||
|
|
||||||
|
# Optional cluster e2e (experimental tier)
|
||||||
|
./tests/raft_e2e_test
|
||||||
|
./tests/raft_writes_e2e_test
|
||||||
|
```
|
||||||
|
|
||||||
|
## Production compose
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export BARADB_JWT_SECRET="$(openssl rand -hex 32)"
|
||||||
|
docker compose -f docker-compose.prod.yml config >/dev/null
|
||||||
|
# must fail without secret:
|
||||||
|
# (unset BARADB_JWT_SECRET; docker compose -f docker-compose.prod.yml config)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Artifacts
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nimble build_release # or: nim c -d:release -o:build/baradadb src/baradadb.nim
|
||||||
|
docker build -t baradb:1.2.0 -t baradb:latest .
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tag
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git tag -a v1.2.0 -m "BaraDB v1.2.0 Production GA (single-node)"
|
||||||
|
git push origin main --tags
|
||||||
|
```
|
||||||
|
|
||||||
|
## Post-release
|
||||||
|
|
||||||
|
- [ ] Smoke: start prod compose, `/health` → ok, auth required for `/query`
|
||||||
|
- [ ] Announce: single-node GA; Raft experimental (link known-limitations)
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
# Production GA (v1.2.0) — Design / cut line
|
# Production GA (v1.2.0) — Design / cut line
|
||||||
|
|
||||||
Date: 2026-07-30
|
Date: 2026-07-30
|
||||||
Status: **Approved direction** — implementation follows the plan
|
Status: **Done (v1.2.0 GA shipped)** — plan
|
||||||
`docs/superpowers/plans/2026-07-30-production-ga.md`.
|
`docs/superpowers/plans/2026-07-30-production-ga.md`.
|
||||||
|
|
||||||
## Problem
|
## Problem
|
||||||
|
|||||||
Executable
+135
@@ -0,0 +1,135 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Backup → wipe → restore → verify drill for BaraDB single-node GA.
|
||||||
|
# Usage: ./scripts/backup-restore-drill.sh
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
|
cd "$ROOT"
|
||||||
|
|
||||||
|
BIN="${BARADB_BIN:-./build/baradadb}"
|
||||||
|
BACKUP_BIN="${BARADB_BACKUP_BIN:-./build/backup}"
|
||||||
|
PORT="${DRILL_PORT:-19472}"
|
||||||
|
HTTP_PORT=$((PORT + 440))
|
||||||
|
WORKDIR="${DRILL_WORKDIR:-/tmp/baradb_backup_drill_$$}"
|
||||||
|
DATA_DIR="$WORKDIR/data"
|
||||||
|
ARCHIVE="$WORKDIR/drill_backup.tar.gz"
|
||||||
|
MARKER="drill-row-$$"
|
||||||
|
|
||||||
|
die() { echo "FAIL: $*" >&2; cleanup; exit 1; }
|
||||||
|
log() { echo "[drill] $*"; }
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
if [[ -n "${SERVER_PID:-}" ]] && kill -0 "$SERVER_PID" 2>/dev/null; then
|
||||||
|
kill "$SERVER_PID" 2>/dev/null || true
|
||||||
|
wait "$SERVER_PID" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
if [[ "${DRILL_KEEP:-1}" == "0" ]]; then
|
||||||
|
rm -rf "$WORKDIR"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
[[ -x "$BIN" ]] || die "missing $BIN — build: nim c -o:build/baradadb src/baradadb.nim"
|
||||||
|
if [[ ! -x "$BACKUP_BIN" ]]; then
|
||||||
|
log "building backup tool..."
|
||||||
|
nim c -d:release -o:build/backup src/barabadb/core/backup.nim || die "cannot build backup tool"
|
||||||
|
BACKUP_BIN=./build/backup
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf "$WORKDIR"
|
||||||
|
mkdir -p "$DATA_DIR"
|
||||||
|
|
||||||
|
start_server() {
|
||||||
|
log "starting server port=$PORT data=$DATA_DIR"
|
||||||
|
# every = fsync each WAL write so kill/backup cannot lose recent puts
|
||||||
|
BARADB_PORT="$PORT" \
|
||||||
|
BARADB_ADDRESS=127.0.0.1 \
|
||||||
|
BARADB_DATA_DIR="$DATA_DIR" \
|
||||||
|
BARADB_LOG_LEVEL=warn \
|
||||||
|
BARADB_AUTH_ENABLED=false \
|
||||||
|
BARADB_WAL_SYNC_MODE=every \
|
||||||
|
"$BIN" >"$WORKDIR/server.log" 2>&1 &
|
||||||
|
SERVER_PID=$!
|
||||||
|
local i=0
|
||||||
|
while (( i < 80 )); do
|
||||||
|
if curl -sf "http://127.0.0.1:${HTTP_PORT}/health" >/dev/null 2>&1; then
|
||||||
|
log "server ready pid=$SERVER_PID"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
sleep 0.15
|
||||||
|
i=$((i + 1))
|
||||||
|
done
|
||||||
|
tail -50 "$WORKDIR/server.log" >&2 || true
|
||||||
|
die "server not healthy on :$HTTP_PORT"
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_server() {
|
||||||
|
if [[ -n "${SERVER_PID:-}" ]] && kill -0 "$SERVER_PID" 2>/dev/null; then
|
||||||
|
log "stopping pid=$SERVER_PID"
|
||||||
|
kill -TERM "$SERVER_PID" 2>/dev/null || true
|
||||||
|
local i=0
|
||||||
|
while kill -0 "$SERVER_PID" 2>/dev/null && (( i < 50 )); do
|
||||||
|
sleep 0.1
|
||||||
|
i=$((i + 1))
|
||||||
|
done
|
||||||
|
if kill -0 "$SERVER_PID" 2>/dev/null; then
|
||||||
|
kill -KILL "$SERVER_PID" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
wait "$SERVER_PID" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
SERVER_PID=""
|
||||||
|
sleep 0.3
|
||||||
|
}
|
||||||
|
|
||||||
|
http_query() {
|
||||||
|
local sql="$1"
|
||||||
|
local payload
|
||||||
|
payload=$(python3 -c "import json,sys; print(json.dumps({'query': sys.argv[1]}))" "$sql")
|
||||||
|
curl -sf -H 'Content-Type: application/json' -d "$payload" \
|
||||||
|
"http://127.0.0.1:${HTTP_PORT}/query"
|
||||||
|
}
|
||||||
|
|
||||||
|
start_server
|
||||||
|
|
||||||
|
log "CREATE + INSERT marker"
|
||||||
|
http_query "CREATE TABLE drill_t (id INT PRIMARY KEY, name STRING)" >/dev/null || die "CREATE failed"
|
||||||
|
http_query "INSERT INTO drill_t (id, name) VALUES (1, '$MARKER')" >/dev/null || die "INSERT failed"
|
||||||
|
body=$(http_query "SELECT name FROM drill_t WHERE id = 1") || die "SELECT before backup failed"
|
||||||
|
echo "$body" | grep -q "$MARKER" || die "marker missing before backup: $body"
|
||||||
|
# allow WAL group/fsync to settle
|
||||||
|
sleep 0.5
|
||||||
|
|
||||||
|
stop_server
|
||||||
|
|
||||||
|
# Prefer multi-db layout used by the server registry
|
||||||
|
DB_ROOT="$DATA_DIR/databases"
|
||||||
|
[[ -d "$DB_ROOT" ]] || die "expected $DB_ROOT after server run"
|
||||||
|
|
||||||
|
log "backup from $DB_ROOT"
|
||||||
|
"$BACKUP_BIN" backup --all-databases --data-root="$DB_ROOT" \
|
||||||
|
--output="$ARCHIVE" --force || die "backup failed"
|
||||||
|
# Sanity: archive must not be tiny empty shell only
|
||||||
|
asize=$(stat -c%s "$ARCHIVE" 2>/dev/null || stat -f%z "$ARCHIVE")
|
||||||
|
(( asize > 200 )) || die "backup archive suspiciously small ($asize bytes)"
|
||||||
|
|
||||||
|
log "wipe data"
|
||||||
|
rm -rf "$DATA_DIR"
|
||||||
|
mkdir -p "$DATA_DIR"
|
||||||
|
|
||||||
|
log "restore multi-db archive into $DB_ROOT"
|
||||||
|
mkdir -p "$DATA_DIR"
|
||||||
|
# Archive layout is databases/<name>/... ; --data-root is the databases/ parent leaf
|
||||||
|
"$BACKUP_BIN" restore --input="$ARCHIVE" --all-databases \
|
||||||
|
--data-root="$DB_ROOT" --force || die "restore failed"
|
||||||
|
|
||||||
|
start_server
|
||||||
|
|
||||||
|
log "verify after restore"
|
||||||
|
body=$(http_query "SELECT name FROM drill_t WHERE id = 1") || die "SELECT after restore failed"
|
||||||
|
echo "$body" | grep -q "$MARKER" || die "marker missing after restore: $body"
|
||||||
|
|
||||||
|
log "PASS backup/restore drill OK marker=$MARKER archive=$ARCHIVE"
|
||||||
|
stop_server
|
||||||
|
trap - EXIT
|
||||||
|
[[ "${DRILL_KEEP:-1}" == "0" ]] && rm -rf "$WORKDIR"
|
||||||
|
exit 0
|
||||||
@@ -250,6 +250,28 @@ proc loadConfig*(): BaraConfig =
|
|||||||
# 2. Environment overrides (highest priority)
|
# 2. Environment overrides (highest priority)
|
||||||
loadConfigFromEnv(result)
|
loadConfigFromEnv(result)
|
||||||
|
|
||||||
|
proc isProductionEnv*(): bool =
|
||||||
|
## True when BARADB_ENV=production (or prod) or BARADB_AUTH_REQUIRED=true.
|
||||||
|
let env = getEnv("BARADB_ENV", "").toLowerAscii()
|
||||||
|
if env == "production" or env == "prod": return true
|
||||||
|
parseEnvBool(getEnv("BARADB_AUTH_REQUIRED", ""), false)
|
||||||
|
|
||||||
|
proc validateProductionConfig*(cfg: BaraConfig) =
|
||||||
|
## Fail closed for production: auth on + non-empty JWT secret.
|
||||||
|
## Call after loadConfig() from the main entrypoint.
|
||||||
|
if not isProductionEnv(): return
|
||||||
|
if not cfg.authEnabled:
|
||||||
|
raise newException(ValueError,
|
||||||
|
"Production refuses to start with auth disabled. " &
|
||||||
|
"Set BARADB_AUTH_ENABLED=true (or unset BARADB_ENV=production for local dev).")
|
||||||
|
if cfg.jwtSecret.len == 0:
|
||||||
|
raise newException(ValueError,
|
||||||
|
"Production refuses to start without BARADB_JWT_SECRET. " &
|
||||||
|
"Generate one: openssl rand -hex 32")
|
||||||
|
if cfg.jwtSecret in ["change-me", "change-me-to-random-32-char-string", "secret", "default"]:
|
||||||
|
raise newException(ValueError,
|
||||||
|
"Production refuses insecure JWT secret placeholder. Set a strong BARADB_JWT_SECRET.")
|
||||||
|
|
||||||
proc getEffectiveJwtSecret*(cfg: BaraConfig): string =
|
proc getEffectiveJwtSecret*(cfg: BaraConfig): string =
|
||||||
if cfg.jwtSecret.len > 0:
|
if cfg.jwtSecret.len > 0:
|
||||||
return cfg.jwtSecret
|
return cfg.jwtSecret
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ proc healthHandler(server: HttpServer): RequestHandler =
|
|||||||
let ctx = newContext(request)
|
let ctx = newContext(request)
|
||||||
var body = %*{
|
var body = %*{
|
||||||
"status": "ok",
|
"status": "ok",
|
||||||
"version": "1.1.6"
|
"version": "1.2.0"
|
||||||
}
|
}
|
||||||
if server.raftNode != nil:
|
if server.raftNode != nil:
|
||||||
let n = server.raftNode
|
let n = server.raftNode
|
||||||
@@ -368,7 +368,7 @@ proc openApiHandler(): RequestHandler =
|
|||||||
let ctx = newContext(request)
|
let ctx = newContext(request)
|
||||||
ctx.json(%*{
|
ctx.json(%*{
|
||||||
"openapi": "3.0.0",
|
"openapi": "3.0.0",
|
||||||
"info": {"title": "BaraDB API", "version": "1.1.6"},
|
"info": {"title": "BaraDB API", "version": "1.2.0"},
|
||||||
"paths": {
|
"paths": {
|
||||||
"/query": {
|
"/query": {
|
||||||
"post": {
|
"post": {
|
||||||
@@ -906,7 +906,7 @@ function showTab(idx){
|
|||||||
}
|
}
|
||||||
setInterval(() => { if(document.querySelectorAll('.panel')[4].classList.contains('active')) loadMetrics() }, 5000)
|
setInterval(() => { if(document.querySelectorAll('.panel')[4].classList.contains('active')) loadMetrics() }, 5000)
|
||||||
</script>
|
</script>
|
||||||
<div class='status' style='text-align:center;padding:10px'>BaraDB v1.1.6 — Multimodal Database Engine</div>
|
<div class='status' style='text-align:center;padding:10px'>BaraDB v1.2.0 — Multimodal Database Engine</div>
|
||||||
</body></html>"""
|
</body></html>"""
|
||||||
request.respond(200, @[("Content-Type", "text/html; charset=utf-8")], html)
|
request.respond(200, @[("Content-Type", "text/html; charset=utf-8")], html)
|
||||||
|
|
||||||
|
|||||||
+7
-2
@@ -278,15 +278,20 @@ proc main() =
|
|||||||
quit(0)
|
quit(0)
|
||||||
|
|
||||||
var config = loadConfig()
|
var config = loadConfig()
|
||||||
|
try:
|
||||||
|
validateProductionConfig(config)
|
||||||
|
except ValueError as e:
|
||||||
|
stderr.writeLine("FATAL: " & e.msg)
|
||||||
|
quit(1)
|
||||||
# Global exclusive gate for multi-thread storage (HTTP workers + TCP + compact)
|
# Global exclusive gate for multi-thread storage (HTTP workers + TCP + compact)
|
||||||
initStorageGate()
|
initStorageGate()
|
||||||
# Init structured logger from config
|
# Init structured logger from config
|
||||||
let logLvl = parseEnum[LogLevel]("ll" & capitalizeAscii(config.logLevel))
|
let logLvl = parseEnum[LogLevel]("ll" & capitalizeAscii(config.logLevel))
|
||||||
defaultLogger = newLogger(logLvl, config.logFile)
|
defaultLogger = newLogger(logLvl, config.logFile)
|
||||||
info("BaraDB v1.1.6 — Multimodal Database Engine")
|
info("BaraDB v1.2.0 — Multimodal Database Engine")
|
||||||
info("Storage gate initialized (serializes HTTP/TCP/compaction access)")
|
info("Storage gate initialized (serializes HTTP/TCP/compaction access)")
|
||||||
|
|
||||||
# Security check: warn if JWT secret is not configured
|
# Security check: warn if JWT secret is not configured (non-production only)
|
||||||
if config.jwtSecret.len == 0:
|
if config.jwtSecret.len == 0:
|
||||||
warn("JWT secret not configured! Set BARADB_JWT_SECRET env var or jwt_secret in config. Using default (INSECURE).")
|
warn("JWT secret not configured! Set BARADB_JWT_SECRET env var or jwt_secret in config. Using default (INSECURE).")
|
||||||
|
|
||||||
|
|||||||
@@ -360,6 +360,29 @@ suite "Bug fixes — UNIQUE index enforcement":
|
|||||||
let c = executeQuery(ctx, parse("CREATE UNIQUE INDEX accts_email ON accts (email)"))
|
let c = executeQuery(ctx, parse("CREATE UNIQUE INDEX accts_email ON accts (email)"))
|
||||||
check not c.success
|
check not c.success
|
||||||
|
|
||||||
|
suite "Production config gate":
|
||||||
|
|
||||||
|
test "validateProductionConfig rejects missing secret":
|
||||||
|
putEnv("BARADB_ENV", "production")
|
||||||
|
defer: delEnv("BARADB_ENV")
|
||||||
|
var cfg = defaultConfig()
|
||||||
|
cfg.authEnabled = true
|
||||||
|
cfg.jwtSecret = ""
|
||||||
|
var msg = ""
|
||||||
|
try:
|
||||||
|
validateProductionConfig(cfg)
|
||||||
|
except ValueError as e:
|
||||||
|
msg = e.msg
|
||||||
|
check "JWT" in msg or "secret" in msg.toLower()
|
||||||
|
|
||||||
|
test "validateProductionConfig accepts strong secret":
|
||||||
|
putEnv("BARADB_ENV", "production")
|
||||||
|
defer: delEnv("BARADB_ENV")
|
||||||
|
var cfg = defaultConfig()
|
||||||
|
cfg.authEnabled = true
|
||||||
|
cfg.jwtSecret = "a".repeat(32)
|
||||||
|
validateProductionConfig(cfg) # must not raise
|
||||||
|
|
||||||
suite "Raft peer address parsing":
|
suite "Raft peer address parsing":
|
||||||
|
|
||||||
test "BARADB_RAFT_CLIENT_PEERS populates raftPeerClientAddrs":
|
test "BARADB_RAFT_CLIENT_PEERS populates raftPeerClientAddrs":
|
||||||
|
|||||||
Reference in New Issue
Block a user