#!/bin/sh # entrypoint.sh — Persist SQLite across HF Spaces rebuilds # # Uses huggingface-cli to upload/download the DB to a private Dataset repo. # HF_TOKEN must be set as a Space secret. # HF_BACKUP_REPO is the dataset repo (e.g. FordAI/hss-pos-backup). LOCAL_DB="/app/data/restaurant.db" BACKUP_REPO="${HF_BACKUP_REPO:-FordAI/hss-pos-backup}" BACKUP_FILE="restaurant.db" SERVER_PORT="${PORT:-7860}" mkdir -p /app/data # ── Helper: get file size portably (works on BusyBox & GNU) ── file_size() { if [ -f "$1" ]; then wc -c < "$1" | tr -d ' ' else echo 0 fi } # ── Restore DB from HF Dataset repo on startup ── if [ -n "$HF_TOKEN" ]; then echo "[PERSIST] Downloading database from $BACKUP_REPO..." if hf download "$BACKUP_REPO" "$BACKUP_FILE" \ --repo-type dataset \ --local-dir /app/data \ --token "$HF_TOKEN" 2>&1; then DB_SIZE=$(file_size "$LOCAL_DB") echo "[PERSIST] Download finished — DB size: $DB_SIZE bytes" if [ "$DB_SIZE" -gt 8192 ]; then echo "[PERSIST] Database restored successfully" # Remove stale WAL/SHM from any previous run rm -f "${LOCAL_DB}-wal" "${LOCAL_DB}-shm" else echo "[PERSIST] Downloaded file too small or empty — starting fresh" rm -f "$LOCAL_DB" fi else echo "[PERSIST] Download failed (expected on first run) — starting fresh" rm -f "$LOCAL_DB" fi else echo "[PERSIST] HF_TOKEN not set — persistence disabled" fi # ── Wait for Go server to be ready ── wait_for_server() { echo "[PERSIST] Waiting for server on port $SERVER_PORT..." TRIES=0 while [ "$TRIES" -lt 60 ]; do if wget -q -O /dev/null "http://127.0.0.1:${SERVER_PORT}/health" 2>/dev/null; then echo "[PERSIST] Server is ready" return 0 fi TRIES=$((TRIES + 1)) sleep 1 done echo "[PERSIST] WARNING: Server not ready after 60s" return 1 } # ── Flush WAL to main DB file before backup ── wal_checkpoint() { echo "[PERSIST] Requesting WAL checkpoint..." RESP=$(wget -q -O - "http://127.0.0.1:${SERVER_PORT}/api/v1/internal/checkpoint" 2>&1) || true echo "[PERSIST] Checkpoint response: $RESP" } # ── Upload DB to HF Dataset repo ── do_backup() { if [ -z "$HF_TOKEN" ]; then echo "[PERSIST] Skipping backup: HF_TOKEN not set" return fi if [ ! -f "$LOCAL_DB" ]; then echo "[PERSIST] Skipping backup: DB file not found" return fi # Checkpoint WAL so all data is in the main .db file wal_checkpoint DB_SIZE=$(file_size "$LOCAL_DB") echo "[PERSIST] DB size after checkpoint: $DB_SIZE bytes" if [ "$DB_SIZE" -le 8192 ]; then echo "[PERSIST] Skipping backup: DB too small ($DB_SIZE bytes)" return fi echo "[PERSIST] Uploading $DB_SIZE bytes to $BACKUP_REPO..." if hf upload "$BACKUP_REPO" "$LOCAL_DB" "$BACKUP_FILE" \ --repo-type dataset \ --token "$HF_TOKEN" 2>&1; then echo "[PERSIST] Backup complete ($DB_SIZE bytes)" else echo "[PERSIST] Backup FAILED (exit code $?)" fi } # ── Start the Go server ── echo "[STARTUP] Launching Go server..." ./server & SERVER_PID=$! # ── Periodic backup (waits for server first) ── backup_loop() { wait_for_server echo "[PERSIST] First backup in 10s..." sleep 10 do_backup while true; do sleep 300 do_backup done } backup_loop & BACKUP_PID=$! # ── Graceful shutdown: final backup ── cleanup() { echo "[PERSIST] Shutdown — running final backup..." do_backup kill "$BACKUP_PID" 2>/dev/null || true exit 0 } trap cleanup TERM INT wait $SERVER_PID