- New caching_custom_backfill_jobs and caching_custom_backfill_batches tables - Admin API (POST create/cancel, GET list) at admin/api/custom_backfill.php - Admin UI form with preset buttons and job status table on Backfill page - Caching daemon module (custom_backfill.c) processes jobs independently - pg_inbox functions for job/batch claim, progress update, and cancel - Three batch modes: author-batched, id-batched, time-window scan - Fixed done_batches overcount on job completion - Admin config now environment-variable driven (C_RELAY_DB_*) - admin/serve.sh supports separate instances for different databases - make_and_restart_relay.sh only kills relay on target port, not all relays
249 lines
9.4 KiB
Bash
Executable File
249 lines
9.4 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# deploy_local.sh - Deploy the local production relay on port 7777.
|
|
#
|
|
# This is SEPARATE from the test relay run by make_and_restart_relay.sh:
|
|
# - Test relay: port 8888, database "crelay", run from build/ by make_and_restart_relay.sh
|
|
# - Local prod: port 7777, database "crelay_prod", systemd service c-relay-pg-local
|
|
#
|
|
# The two relays share one PostgreSQL server (localhost:5432) but use
|
|
# different databases, so they are fully isolated: separate config tables,
|
|
# separate keypairs, separate event stores, separate admin keys.
|
|
#
|
|
# Usage:
|
|
# ./deploy_local.sh # install (first time) or update (subsequent)
|
|
# ./deploy_local.sh --install # force full install steps
|
|
# ./deploy_local.sh --status # just show service status
|
|
#
|
|
# Prerequisites:
|
|
# - build/c_relay_pg_static_x86_64 exists (run ./build_static.sh first)
|
|
# - PostgreSQL running on localhost:5432 with role "crelay" (password "crelay")
|
|
# - Database "crelay_prod" exists (this script creates it if missing)
|
|
|
|
set -euo pipefail
|
|
|
|
# --- Configuration ---
|
|
LOCAL_BINARY="build/c_relay_pg_static_x86_64"
|
|
LOCAL_CACHING_BINARY="build/caching_relay"
|
|
DEPLOY_DIR="$HOME/Storage/c_relay_pg"
|
|
DEPLOYED_BINARY="$DEPLOY_DIR/crelay"
|
|
DEPLOYED_CACHING_BINARY="$DEPLOY_DIR/caching_relay"
|
|
SERVICE_NAME="c-relay-pg-local"
|
|
SERVICE_FILE="systemd/c-relay-pg-local.service"
|
|
INSTALLED_SERVICE_PATH="/etc/systemd/system/${SERVICE_NAME}.service"
|
|
|
|
# Admin dashboard paths
|
|
LOCAL_ADMIN_DIR="admin"
|
|
PROD_ADMIN_DIR="admin_prod"
|
|
PROD_ADMIN_PORT=7077
|
|
|
|
# Database config (must match the service file ExecStart)
|
|
DB_HOST="127.0.0.1"
|
|
DB_NAME="crelay_prod"
|
|
DB_USER="crelay"
|
|
DB_PASSWORD="crelay"
|
|
RELAY_PORT=7777
|
|
|
|
# --- Helpers ---
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
success() { echo -e "${GREEN}[OK]${NC} $1"; }
|
|
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
|
|
|
# --- Parse args ---
|
|
ACTION="auto"
|
|
case "${1:-}" in
|
|
--install) ACTION="install" ;;
|
|
--status) ACTION="status" ;;
|
|
--help|-h)
|
|
echo "Usage: $0 [--install|--status]"
|
|
echo ""
|
|
echo " (no arg) Install if needed, then update binary and restart"
|
|
echo " --install Force full install steps (service file, database, dirs)"
|
|
echo " --status Just show service status and exit"
|
|
exit 0
|
|
;;
|
|
esac
|
|
|
|
# --- Status-only mode ---
|
|
if [ "$ACTION" = "status" ]; then
|
|
info "Service status for ${SERVICE_NAME}:"
|
|
sudo systemctl status "$SERVICE_NAME" --no-pager -l || true
|
|
info "Port ${RELAY_PORT} listeners:"
|
|
ss -tlnp 2>/dev/null | grep ":${RELAY_PORT}" || echo " (nothing listening on ${RELAY_PORT})"
|
|
exit 0
|
|
fi
|
|
|
|
# --- Check binary exists ---
|
|
if [ ! -f "$LOCAL_BINARY" ]; then
|
|
error "Binary not found: $LOCAL_BINARY"
|
|
echo "Build it first with: ./build_static.sh"
|
|
exit 1
|
|
fi
|
|
|
|
# --- Check service file exists ---
|
|
if [ ! -f "$SERVICE_FILE" ]; then
|
|
error "Service file not found: $SERVICE_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
# --- Ensure crelay_prod database exists ---
|
|
info "Checking PostgreSQL database '${DB_NAME}'..."
|
|
if ! PGPASSWORD="$DB_PASSWORD" psql -U "$DB_USER" -d "$DB_NAME" -h "$DB_HOST" -c "SELECT 1" >/dev/null 2>&1; then
|
|
info "Database '${DB_NAME}' does not exist or is not accessible. Creating it..."
|
|
if ! sudo -u postgres psql -tAc "SELECT 1 FROM pg_roles WHERE rolname='${DB_USER}'" | grep -q 1; then
|
|
error "PostgreSQL role '${DB_USER}' does not exist. Create it first:"
|
|
echo " sudo -u postgres psql -c \"CREATE ROLE ${DB_USER} LOGIN PASSWORD '${DB_PASSWORD}'\""
|
|
exit 1
|
|
fi
|
|
sudo -u postgres createdb --owner="$DB_USER" "$DB_NAME"
|
|
success "Created database '${DB_NAME}' owned by '${DB_USER}'"
|
|
else
|
|
success "Database '${DB_NAME}' already exists"
|
|
fi
|
|
|
|
# --- Ensure deploy directory exists ---
|
|
info "Ensuring deploy directory exists: $DEPLOY_DIR"
|
|
mkdir -p "$DEPLOY_DIR"
|
|
success "Deploy directory ready: $DEPLOY_DIR"
|
|
|
|
# --- Install or update service file ---
|
|
SERVICE_NEEDS_INSTALL=0
|
|
if [ "$ACTION" = "install" ]; then
|
|
SERVICE_NEEDS_INSTALL=1
|
|
elif [ ! -f "$INSTALLED_SERVICE_PATH" ]; then
|
|
warn "Service file not installed at $INSTALLED_SERVICE_PATH"
|
|
SERVICE_NEEDS_INSTALL=1
|
|
elif ! diff -q "$SERVICE_FILE" "$INSTALLED_SERVICE_PATH" >/dev/null 2>&1; then
|
|
warn "Service file has changed, updating $INSTALLED_SERVICE_PATH"
|
|
SERVICE_NEEDS_INSTALL=1
|
|
fi
|
|
|
|
if [ "$SERVICE_NEEDS_INSTALL" -eq 1 ]; then
|
|
info "Installing service file to $INSTALLED_SERVICE_PATH"
|
|
sudo cp "$SERVICE_FILE" "$INSTALLED_SERVICE_PATH"
|
|
sudo chown root:root "$INSTALLED_SERVICE_PATH"
|
|
sudo chmod 644 "$INSTALLED_SERVICE_PATH"
|
|
sudo systemctl daemon-reload
|
|
success "Service file installed and daemon reloaded"
|
|
fi
|
|
|
|
# --- Stop service before swapping binary ---
|
|
info "Stopping ${SERVICE_NAME} (if running)..."
|
|
sudo systemctl stop "$SERVICE_NAME" 2>/dev/null || true
|
|
|
|
# --- Kill anything on port 7777 (safety) ---
|
|
PORT_PID=$(lsof -ti :"$RELAY_PORT" 2>/dev/null || true)
|
|
if [ -n "$PORT_PID" ]; then
|
|
warn "Port ${RELAY_PORT} in use by PID(s) $PORT_PID, killing..."
|
|
kill -9 $PORT_PID 2>/dev/null || true
|
|
sleep 1
|
|
fi
|
|
|
|
# --- Kill stale caching_relay processes from the prod deploy dir ---
|
|
CACHING_PIDS=$(pgrep -f "$DEPLOYED_CACHING_BINARY" || true)
|
|
if [ -n "$CACHING_PIDS" ]; then
|
|
warn "Killing stale caching_relay processes: $CACHING_PIDS"
|
|
kill -9 $CACHING_PIDS 2>/dev/null || true
|
|
sleep 1
|
|
fi
|
|
|
|
# --- Install relay binary ---
|
|
info "Installing relay binary: $LOCAL_BINARY -> $DEPLOYED_BINARY"
|
|
cp "$LOCAL_BINARY" "$DEPLOYED_BINARY"
|
|
chmod +x "$DEPLOYED_BINARY"
|
|
success "Relay binary installed"
|
|
|
|
# --- Install caching binary (static MUSL build) if present ---
|
|
if [ -f "$LOCAL_CACHING_BINARY" ]; then
|
|
info "Installing caching binary: $LOCAL_CACHING_BINARY -> $DEPLOYED_CACHING_BINARY"
|
|
cp "$LOCAL_CACHING_BINARY" "$DEPLOYED_CACHING_BINARY"
|
|
chmod +x "$DEPLOYED_CACHING_BINARY"
|
|
success "Caching binary installed (not auto-started; enable via config when ready)"
|
|
else
|
|
warn "Caching binary not found at $LOCAL_CACHING_BINARY — skipping"
|
|
warn "Build it with: cd caching && make"
|
|
fi
|
|
|
|
# --- Sync admin dashboard files to production admin directory ---
|
|
info "Syncing admin dashboard to ${PROD_ADMIN_DIR}/..."
|
|
rsync -a --delete \
|
|
--exclude='lib/config.php' \
|
|
--exclude='php_server.log' \
|
|
--exclude='cache/' \
|
|
"${LOCAL_ADMIN_DIR}/" "${PROD_ADMIN_DIR}/"
|
|
# Preserve the production-specific config (points to crelay_prod)
|
|
cp "${PROD_ADMIN_DIR}/lib/config.php" "${PROD_ADMIN_DIR}/lib/config.php.prod" 2>/dev/null || true
|
|
cp "${LOCAL_ADMIN_DIR}/lib/config.php" "${PROD_ADMIN_DIR}/lib/config.php"
|
|
# Restore the production config (it already points to crelay_prod after our fix)
|
|
if [ -f "${PROD_ADMIN_DIR}/lib/config.php.prod" ]; then
|
|
cp "${PROD_ADMIN_DIR}/lib/config.php.prod" "${PROD_ADMIN_DIR}/lib/config.php"
|
|
rm "${PROD_ADMIN_DIR}/lib/config.php.prod"
|
|
fi
|
|
success "Admin dashboard synced"
|
|
|
|
# --- Restart production admin PHP server ---
|
|
info "Restarting production admin PHP server on port ${PROD_ADMIN_PORT}..."
|
|
pkill -f "php -S 127.0.0.1:${PROD_ADMIN_PORT}" 2>/dev/null || true
|
|
sleep 1
|
|
setsid php -S 127.0.0.1:${PROD_ADMIN_PORT} -t "${PROD_ADMIN_DIR}" > "${PROD_ADMIN_DIR}/php_server.log" 2>&1 < /dev/null &
|
|
disown $! 2>/dev/null
|
|
sleep 1
|
|
success "Production admin PHP server restarted on http://127.0.0.1:${PROD_ADMIN_PORT}"
|
|
|
|
# --- Enable and start the service ---
|
|
info "Enabling and starting ${SERVICE_NAME}..."
|
|
sudo systemctl enable "$SERVICE_NAME"
|
|
sudo systemctl restart "$SERVICE_NAME"
|
|
|
|
# --- Wait and verify ---
|
|
sleep 3
|
|
|
|
info "Service status:"
|
|
sudo systemctl status "$SERVICE_NAME" --no-pager -l || true
|
|
|
|
# --- Health check ---
|
|
info "Health check on port ${RELAY_PORT}..."
|
|
HEALTH_CODE=$(curl -s -o /dev/null -w "%{http_code}" "http://127.0.0.1:${RELAY_PORT}" 2>/dev/null || echo "000")
|
|
if [ "$HEALTH_CODE" = "200" ]; then
|
|
success "Relay is responding on http://127.0.0.1:${RELAY_PORT} (HTTP $HEALTH_CODE)"
|
|
else
|
|
warn "Relay returned HTTP $HEALTH_CODE on port ${RELAY_PORT} (may still be starting up)"
|
|
echo " Check logs with: sudo journalctl -u ${SERVICE_NAME} -f"
|
|
fi
|
|
|
|
# --- Database verification ---
|
|
info "Verifying database connection..."
|
|
if PGPASSWORD="$DB_PASSWORD" psql -U "$DB_USER" -d "$DB_NAME" -h "$DB_HOST" -c "SELECT current_user, current_database();" >/dev/null 2>&1; then
|
|
success "Database connection OK: ${DB_USER}@${DB_NAME}"
|
|
else
|
|
error "Could not connect to database ${DB_NAME} as ${DB_USER}"
|
|
fi
|
|
|
|
echo ""
|
|
echo "=========================================="
|
|
success "Local production relay deployed"
|
|
echo "=========================================="
|
|
echo "WebSocket endpoint: ws://127.0.0.1:${RELAY_PORT}"
|
|
echo "HTTP endpoint: http://127.0.0.1:${RELAY_PORT}"
|
|
echo "Admin dashboard: http://127.0.0.1:${PROD_ADMIN_PORT}"
|
|
echo "Database: ${DB_NAME} (isolated from test relay's 'crelay' db)"
|
|
echo "Service: ${SERVICE_NAME}"
|
|
echo "Deploy dir: $DEPLOY_DIR"
|
|
echo ""
|
|
echo "Logs: sudo journalctl -u ${SERVICE_NAME} -f"
|
|
echo "Status: ./deploy_local.sh --status"
|
|
echo ""
|
|
warn "IMPORTANT: On first startup, the admin private key is printed ONCE in the logs."
|
|
echo " Retrieve it with:"
|
|
echo " sudo journalctl -u ${SERVICE_NAME} --since=\"5 min ago\" | grep -i \"admin.*key\""
|
|
echo ""
|
|
echo "Test relay (port 8888) is unaffected — run it separately with ./make_and_restart_relay.sh"
|
|
echo "Test admin UI: http://127.0.0.1:8088"
|