Spaces:
Running
Running
| set -e | |
| DB_PATH="/data/.flowise/database.sqlite" | |
| BACKUP_INTERVAL_SECONDS=${BACKUP_INTERVAL_SECONDS:-86400} | |
| AUTO_RESTART_DAYS=${AUTO_RESTART_DAYS:-7} | |
| HEALTH_CHECK_INTERVAL=${HEALTH_CHECK_INTERVAL:-3600} | |
| log() { | |
| echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | |
| } | |
| log_error() { | |
| echo "[$(date +'%Y-%m-%d %H:%M:%S')] ❌ $1" >&2 | |
| } | |
| echo "" | |
| echo "═══════════════════════════════════════" | |
| echo " 🚀 Flowise + Neon Backup (Production)" | |
| echo "═══════════════════════════════════════" | |
| echo "" | |
| restore_from_neon() { | |
| if [ -z "$NEON_PASSWORD" ] || [ -z "$NEON_HOST" ]; then | |
| log "⚠️ Neon not configured - skipping restore" | |
| return 0 | |
| fi | |
| log "📥 Restoring from Neon..." | |
| PGPASSWORD="$NEON_PASSWORD" psql "postgresql://${NEON_USER}@${NEON_HOST}/${NEON_DB}?sslmode=require" \ | |
| -A -t -q -c "SELECT sql_content_b64 FROM flowise_backups ORDER BY backup_date DESC LIMIT 1;" \ | |
| > /tmp/backup_b64.txt 2>/dev/null || true | |
| if [ ! -f /tmp/backup_b64.txt ]; then | |
| log "ℹ️ No backup found (first run)" | |
| return 0 | |
| fi | |
| FILE_SIZE=$(wc -c < /tmp/backup_b64.txt 2>/dev/null || echo "0") | |
| if [ "$FILE_SIZE" -lt 100 ]; then | |
| log "ℹ️ No valid backup found" | |
| rm -f /tmp/backup_b64.txt 2>/dev/null || true | |
| return 0 | |
| fi | |
| mkdir -p /data/.flowise | |
| rm -f "$DB_PATH" "${DB_PATH}-shm" "${DB_PATH}-wal" 2>/dev/null || true | |
| base64 -d /tmp/backup_b64.txt > /tmp/neon_backup.sql 2>/dev/null || true | |
| sqlite3 "$DB_PATH" < /tmp/neon_backup.sql 2>/dev/null || true | |
| if [ -f "$DB_PATH" ]; then | |
| USER_COUNT=$(sqlite3 "$DB_PATH" "SELECT COUNT(*) FROM user;" 2>/dev/null || echo "0") | |
| ORG_COUNT=$(sqlite3 "$DB_PATH" "SELECT COUNT(*) FROM organization;" 2>/dev/null || echo "0") | |
| CF_COUNT=$(sqlite3 "$DB_PATH" "SELECT COUNT(*) FROM chat_flow;" 2>/dev/null || echo "0") | |
| CRED_COUNT=$(sqlite3 "$DB_PATH" "SELECT COUNT(*) FROM credential;" 2>/dev/null || echo "0") | |
| if [ "$USER_COUNT" -gt 0 ] && [ "$ORG_COUNT" -gt 0 ]; then | |
| log "✅ Restored: $USER_COUNT user(s), $ORG_COUNT org(s), $CF_COUNT flow(s), $CRED_COUNT cred(s)" | |
| else | |
| log "ℹ️ Empty backup restored" | |
| fi | |
| else | |
| log_error "Database restore failed" | |
| fi | |
| rm -f /tmp/backup_b64.txt /tmp/neon_backup.sql 2>/dev/null || true | |
| } | |
| start_flowise() { | |
| log "🚀 Starting Flowise..." | |
| npx flowise start --PORT=7860 2>&1 | grep -E "^\[|ERROR|error|Error" & | |
| FLOWISE_PID=$! | |
| local attempts=0 | |
| local max_attempts=60 | |
| while [ $attempts -lt $max_attempts ]; do | |
| if ! kill -0 $FLOWISE_PID 2>/dev/null; then | |
| log_error "Flowise process died" | |
| exit 1 | |
| fi | |
| if curl -sf http://localhost:7860 > /dev/null 2>&1; then | |
| log "✅ Flowise ready (PID: $FLOWISE_PID)" | |
| return 0 | |
| fi | |
| attempts=$((attempts + 1)) | |
| sleep 2 | |
| done | |
| log_error "Flowise startup timeout" | |
| exit 1 | |
| } | |
| start_health_monitor() { | |
| ( | |
| sleep 300 | |
| while true; do | |
| if ! kill -0 $FLOWISE_PID 2>/dev/null; then | |
| log_error "Health: Flowise died - triggering restart" | |
| exit 1 | |
| fi | |
| if ! curl -sf http://localhost:7860 > /dev/null 2>&1; then | |
| log_error "Health: Flowise unresponsive - triggering restart" | |
| kill $FLOWISE_PID 2>/dev/null || true | |
| exit 1 | |
| fi | |
| sleep $HEALTH_CHECK_INTERVAL | |
| done | |
| ) & | |
| HEALTH_PID=$! | |
| } | |
| start_restart_timer() { | |
| if [ "$AUTO_RESTART_DAYS" -le 0 ]; then | |
| return 0 | |
| fi | |
| ( | |
| sleep $((AUTO_RESTART_DAYS * 86400)) | |
| log "♻️ Scheduled restart ($AUTO_RESTART_DAYS days)" | |
| kill $FLOWISE_PID 2>/dev/null || true | |
| ) & | |
| RESTART_PID=$! | |
| } | |
| start_backup_service() { | |
| if [ -z "$NEON_PASSWORD" ] || [ -z "$NEON_HOST" ]; then | |
| log "⚠️ Neon not configured - backups disabled" | |
| return 0 | |
| fi | |
| /data/backup.sh & | |
| BACKUP_PID=$! | |
| } | |
| cleanup() { | |
| log "🛑 Shutting down..." | |
| kill $FLOWISE_PID 2>/dev/null || true | |
| kill $BACKUP_PID 2>/dev/null || true | |
| kill $HEALTH_PID 2>/dev/null || true | |
| kill $RESTART_PID 2>/dev/null || true | |
| exit 0 | |
| } | |
| trap cleanup SIGTERM SIGINT | |
| restore_from_neon | |
| start_flowise | |
| start_backup_service | |
| start_health_monitor | |
| start_restart_timer | |
| INTERVAL_HOURS=$((BACKUP_INTERVAL_SECONDS / 3600)) | |
| echo "" | |
| echo "═══════════════════════════════════════" | |
| echo " ✅ FLOWISE RUNNING" | |
| echo "═══════════════════════════════════════" | |
| echo " 📦 Backup: Every ${INTERVAL_HOURS}h" | |
| echo " 🏥 Health: Every $((HEALTH_CHECK_INTERVAL / 60))m" | |
| if [ "$AUTO_RESTART_DAYS" -gt 0 ]; then | |
| echo " ♻️ Restart: ${AUTO_RESTART_DAYS} days" | |
| else | |
| echo " ♻️ Restart: Manual only" | |
| fi | |
| echo "═══════════════════════════════════════" | |
| echo "" | |
| wait $FLOWISE_PID | |