From e1e949cf6504ddb5547e7a7ed71510afdde67cec Mon Sep 17 00:00:00 2001 From: perf3ct Date: Fri, 13 Jun 2025 14:27:31 +0000 Subject: [PATCH] feat(migrations): try to fix the migrations service --- Cargo.toml | 2 +- migrations/20240101000000_initial_schema.sql | 62 ++++++++++++++++++++ src/main.rs | 46 ++++++++++++--- 3 files changed, 101 insertions(+), 9 deletions(-) create mode 100644 migrations/20240101000000_initial_schema.sql diff --git a/Cargo.toml b/Cargo.toml index 9531e36..4059a7e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ tower = { version = "0.4", features = ["util"] } tower-http = { version = "0.5", features = ["cors", "fs"] } serde = { version = "1", features = ["derive"] } serde_json = "1" -sqlx = { version = "0.7", features = ["runtime-tokio-rustls", "postgres", "sqlite", "chrono", "uuid"] } +sqlx = { version = "0.7", features = ["runtime-tokio-rustls", "postgres", "sqlite", "chrono", "uuid", "migrate"] } regex = "1.0" uuid = { version = "1", features = ["v4", "serde"] } chrono = { version = "0.4", features = ["serde"] } diff --git a/migrations/20240101000000_initial_schema.sql b/migrations/20240101000000_initial_schema.sql new file mode 100644 index 0000000..55d7702 --- /dev/null +++ b/migrations/20240101000000_initial_schema.sql @@ -0,0 +1,62 @@ +-- Create extensions +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; +CREATE EXTENSION IF NOT EXISTS "pg_trgm"; + +-- Create users table +CREATE TABLE IF NOT EXISTS users ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + username VARCHAR(255) UNIQUE NOT NULL, + email VARCHAR(255) UNIQUE NOT NULL, + password_hash VARCHAR(255) NOT NULL, + created_at TIMESTAMPTZ DEFAULT NOW(), + updated_at TIMESTAMPTZ DEFAULT NOW() +); + +-- Create documents table +CREATE TABLE IF NOT EXISTS documents ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + filename VARCHAR(255) NOT NULL, + original_filename VARCHAR(255) NOT NULL, + file_path VARCHAR(500) NOT NULL, + file_size BIGINT NOT NULL, + mime_type VARCHAR(100) NOT NULL, + content TEXT, + ocr_text TEXT, + tags TEXT[] DEFAULT '{}', + created_at TIMESTAMPTZ DEFAULT NOW(), + updated_at TIMESTAMPTZ DEFAULT NOW(), + user_id UUID REFERENCES users(id) ON DELETE CASCADE +); + +-- Create indexes +CREATE INDEX IF NOT EXISTS idx_documents_user_id ON documents(user_id); +CREATE INDEX IF NOT EXISTS idx_documents_filename ON documents(filename); +CREATE INDEX IF NOT EXISTS idx_documents_mime_type ON documents(mime_type); +CREATE INDEX IF NOT EXISTS idx_documents_tags ON documents USING GIN(tags); +CREATE INDEX IF NOT EXISTS idx_documents_content_search ON documents USING GIN(to_tsvector('english', COALESCE(content, '') || ' ' || COALESCE(ocr_text, ''))); +CREATE INDEX IF NOT EXISTS idx_documents_filename_trgm ON documents USING GIN(filename gin_trgm_ops); +CREATE INDEX IF NOT EXISTS idx_documents_content_trgm ON documents USING GIN((COALESCE(content, '') || ' ' || COALESCE(ocr_text, '')) gin_trgm_ops); + +-- Create settings table +CREATE TABLE IF NOT EXISTS settings ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + user_id UUID REFERENCES users(id) ON DELETE CASCADE UNIQUE, + ocr_language VARCHAR(10) DEFAULT 'eng', + concurrent_ocr_jobs INT DEFAULT 4, + ocr_timeout_seconds INT DEFAULT 300, + max_file_size_mb INT DEFAULT 50, + allowed_file_types TEXT[] DEFAULT ARRAY['pdf', 'png', 'jpg', 'jpeg', 'tiff', 'bmp', 'txt'], + auto_rotate_images BOOLEAN DEFAULT TRUE, + enable_image_preprocessing BOOLEAN DEFAULT TRUE, + search_results_per_page INT DEFAULT 25, + search_snippet_length INT DEFAULT 200, + fuzzy_search_threshold REAL DEFAULT 0.8, + retention_days INT, + enable_auto_cleanup BOOLEAN DEFAULT FALSE, + enable_compression BOOLEAN DEFAULT FALSE, + memory_limit_mb INT DEFAULT 512, + cpu_priority VARCHAR(10) DEFAULT 'normal', + enable_background_ocr BOOLEAN DEFAULT TRUE, + created_at TIMESTAMPTZ DEFAULT NOW(), + updated_at TIMESTAMPTZ DEFAULT NOW() +); \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 1223288..9fcdaa0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,7 @@ use axum::{ routing::get, Router, }; +use sqlx::Row; use std::sync::Arc; use tower_http::{cors::CorsLayer, services::ServeDir}; use tracing::{info, error}; @@ -41,16 +42,45 @@ async fn main() -> Result<(), Box> { let config = Config::from_env()?; let db = Database::new(&config.database_url).await?; - db.migrate().await?; + // Don't run the old migration system - let SQLx handle everything + // db.migrate().await?; // Run SQLx migrations - sqlx::migrate!("./migrations") - .run(&db.pool) - .await - .map_err(|e| { - error!("Failed to run migrations: {}", e); - e - })?; + info!("Running SQLx migrations..."); + let migrations = sqlx::migrate!("./migrations"); + info!("Found {} migrations", migrations.migrations.len()); + + for migration in migrations.migrations.iter() { + info!("Migration available: {} - {}", migration.version, migration.description); + } + + // Check current migration status + let applied_result = sqlx::query("SELECT version, description FROM _sqlx_migrations ORDER BY version") + .fetch_all(&db.pool) + .await; + + match applied_result { + Ok(rows) => { + info!("Currently applied migrations:"); + for row in rows { + let version: i64 = row.get("version"); + let description: String = row.get("description"); + info!(" - {} {}", version, description); + } + } + Err(e) => { + info!("No existing migrations found (this is normal for first run): {}", e); + } + } + + let result = migrations.run(&db.pool).await; + match result { + Ok(_) => info!("SQLx migrations completed successfully"), + Err(e) => { + error!("Failed to run SQLx migrations: {}", e); + return Err(e.into()); + } + } // Seed admin user seed::seed_admin_user(&db).await?;