enki b3204ea07a
Some checks are pending
CI Pipeline / Run Tests (push) Waiting to run
CI Pipeline / Lint Code (push) Waiting to run
CI Pipeline / Security Scan (push) Waiting to run
CI Pipeline / Build Docker Images (push) Blocked by required conditions
CI Pipeline / E2E Tests (push) Blocked by required conditions
first commit
2025-08-18 00:40:15 -07:00

233 lines
7.4 KiB
Bash
Executable File

#!/bin/bash
# Database Migration Script
# Handles database schema migrations and data updates
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
DB_PATH="${PROJECT_ROOT}/data/metadata.db"
echo "🔄 Database Migration Script"
echo "==========================="
cd "$PROJECT_ROOT"
# Check if database exists
if [ ! -f "$DB_PATH" ]; then
echo "❌ Database not found: $DB_PATH"
echo "Please ensure the gateway has been initialized first"
exit 1
fi
# Create backup before migration
echo "💾 Creating pre-migration backup..."
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="./backups/pre_migration_${TIMESTAMP}.sql"
mkdir -p backups
sqlite3 "$DB_PATH" .dump > "$BACKUP_FILE"
echo "✅ Backup created: $BACKUP_FILE"
# Check current schema version
echo "📊 Checking current schema..."
CURRENT_TABLES=$(sqlite3 "$DB_PATH" ".tables")
echo "Current tables: $CURRENT_TABLES"
# Migration functions
run_migration() {
local version="$1"
local description="$2"
local sql="$3"
echo "🔄 Migration $version: $description"
if sqlite3 "$DB_PATH" "$sql"; then
echo "✅ Migration $version completed"
# Log migration
sqlite3 "$DB_PATH" "INSERT OR IGNORE INTO schema_migrations (version, description, applied_at) VALUES ('$version', '$description', datetime('now'));"
else
echo "❌ Migration $version failed"
exit 1
fi
}
# Create migrations table if it doesn't exist
echo "🗄️ Creating migrations table..."
sqlite3 "$DB_PATH" "
CREATE TABLE IF NOT EXISTS schema_migrations (
version TEXT PRIMARY KEY,
description TEXT NOT NULL,
applied_at DATETIME DEFAULT CURRENT_TIMESTAMP
);"
# Check which migrations have been applied
APPLIED_MIGRATIONS=$(sqlite3 "$DB_PATH" "SELECT version FROM schema_migrations;" 2>/dev/null || echo "")
echo "Applied migrations: $APPLIED_MIGRATIONS"
# Migration 1: Add performance indexes
if ! echo "$APPLIED_MIGRATIONS" | grep -q "001_performance_indexes"; then
run_migration "001_performance_indexes" "Add performance indexes" "
CREATE INDEX IF NOT EXISTS idx_files_owner_pubkey ON files(owner_pubkey);
CREATE INDEX IF NOT EXISTS idx_files_storage_type ON files(storage_type);
CREATE INDEX IF NOT EXISTS idx_files_access_level ON files(access_level);
CREATE INDEX IF NOT EXISTS idx_files_size ON files(size);
CREATE INDEX IF NOT EXISTS idx_files_last_access ON files(last_access);
CREATE INDEX IF NOT EXISTS idx_chunks_chunk_hash ON chunks(chunk_hash);
CREATE INDEX IF NOT EXISTS idx_users_storage_used ON users(storage_used);
"
else
echo "⏭️ Skipping migration 001_performance_indexes (already applied)"
fi
# Migration 2: Add monitoring columns
if ! echo "$APPLIED_MIGRATIONS" | grep -q "002_monitoring_columns"; then
run_migration "002_monitoring_columns" "Add monitoring and metrics columns" "
ALTER TABLE files ADD COLUMN download_count INTEGER DEFAULT 0;
ALTER TABLE files ADD COLUMN stream_count INTEGER DEFAULT 0;
ALTER TABLE users ADD COLUMN bandwidth_used INTEGER DEFAULT 0;
ALTER TABLE users ADD COLUMN api_requests INTEGER DEFAULT 0;
CREATE INDEX IF NOT EXISTS idx_files_download_count ON files(download_count);
CREATE INDEX IF NOT EXISTS idx_files_stream_count ON files(stream_count);
"
else
echo "⏭️ Skipping migration 002_monitoring_columns (already applied)"
fi
# Migration 3: Add cache tables
if ! echo "$APPLIED_MIGRATIONS" | grep -q "003_cache_tables"; then
run_migration "003_cache_tables" "Add cache management tables" "
CREATE TABLE IF NOT EXISTS cache_entries (
cache_key TEXT PRIMARY KEY,
cache_value BLOB,
cache_type TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
expires_at DATETIME,
hit_count INTEGER DEFAULT 0
);
CREATE INDEX IF NOT EXISTS idx_cache_entries_type ON cache_entries(cache_type);
CREATE INDEX IF NOT EXISTS idx_cache_entries_expires ON cache_entries(expires_at);
"
else
echo "⏭️ Skipping migration 003_cache_tables (already applied)"
fi
# Migration 4: Add rate limiting tables
if ! echo "$APPLIED_MIGRATIONS" | grep -q "004_rate_limiting"; then
run_migration "004_rate_limiting" "Add rate limiting tracking" "
CREATE TABLE IF NOT EXISTS rate_limit_events (
id INTEGER PRIMARY KEY,
client_ip TEXT NOT NULL,
limit_type TEXT NOT NULL,
blocked BOOLEAN DEFAULT FALSE,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_rate_limit_ip ON rate_limit_events(client_ip);
CREATE INDEX IF NOT EXISTS idx_rate_limit_timestamp ON rate_limit_events(timestamp);
"
else
echo "⏭️ Skipping migration 004_rate_limiting (already applied)"
fi
# Data consistency checks
echo "🔍 Running data consistency checks..."
# Check for orphaned chunks
ORPHANED_CHUNKS=$(sqlite3 "$DB_PATH" "
SELECT COUNT(*) FROM chunks c
LEFT JOIN files f ON c.file_hash = f.hash
WHERE f.hash IS NULL;
")
if [ "$ORPHANED_CHUNKS" -gt 0 ]; then
echo "⚠️ Found $ORPHANED_CHUNKS orphaned chunks"
read -p "Remove orphaned chunks? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
sqlite3 "$DB_PATH" "
DELETE FROM chunks WHERE file_hash NOT IN (SELECT hash FROM files);
"
echo "✅ Orphaned chunks removed"
fi
else
echo "✅ No orphaned chunks found"
fi
# Check for expired sessions
EXPIRED_SESSIONS=$(sqlite3 "$DB_PATH" "
SELECT COUNT(*) FROM sessions
WHERE expires_at < datetime('now');
")
if [ "$EXPIRED_SESSIONS" -gt 0 ]; then
echo "🧹 Cleaning up $EXPIRED_SESSIONS expired sessions..."
sqlite3 "$DB_PATH" "DELETE FROM sessions WHERE expires_at < datetime('now');"
echo "✅ Expired sessions cleaned"
else
echo "✅ No expired sessions found"
fi
# Update storage statistics
echo "📊 Updating storage statistics..."
sqlite3 "$DB_PATH" "
UPDATE users SET
storage_used = (
SELECT COALESCE(SUM(size), 0)
FROM files
WHERE owner_pubkey = users.pubkey
),
file_count = (
SELECT COUNT(*)
FROM files
WHERE owner_pubkey = users.pubkey
);
"
echo "✅ Storage statistics updated"
# Vacuum database for performance
echo "🧹 Optimizing database..."
sqlite3 "$DB_PATH" "VACUUM;"
sqlite3 "$DB_PATH" "ANALYZE;"
echo "✅ Database optimized"
# Final validation
echo "🔍 Final validation..."
# Check table integrity
INTEGRITY_CHECK=$(sqlite3 "$DB_PATH" "PRAGMA integrity_check;")
if [ "$INTEGRITY_CHECK" = "ok" ]; then
echo "✅ Database integrity check passed"
else
echo "❌ Database integrity check failed: $INTEGRITY_CHECK"
FAILED_CHECKS=$((FAILED_CHECKS + 1))
fi
# Check foreign key constraints
FK_CHECK=$(sqlite3 "$DB_PATH" "PRAGMA foreign_key_check;")
if [ -z "$FK_CHECK" ]; then
echo "✅ Foreign key constraints valid"
else
echo "⚠️ Foreign key constraint violations found: $FK_CHECK"
fi
echo ""
echo "📊 Migration Summary"
echo "==================="
echo "Total checks: $TOTAL_CHECKS"
echo "Passed: $PASSED_CHECKS"
echo "Failed: $FAILED_CHECKS"
if [ $FAILED_CHECKS -eq 0 ]; then
echo ""
echo "🎉 All migrations and checks completed successfully!"
echo "✅ Database is healthy and up-to-date"
exit 0
else
echo ""
echo "⚠️ Some checks failed"
echo "💾 Backup available at: $BACKUP_FILE"
echo "🔧 Please investigate and fix issues"
exit 1
fi