Files
Baradb/scripts/backup-restore-drill.sh
dimgigov 09f462f467
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
release: v1.2.0 Production GA (single-node)
- 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)
2026-07-30 21:52:21 +03:00

136 lines
4.1 KiB
Bash
Executable File

#!/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