openserve 2.0.3

A modern, high-performance, AI-enhanced file server built in Rust
Documentation
//! Storage service for database operations

use anyhow::Result;
use sqlx::{Pool, Sqlite, SqlitePool};
use tracing::{debug, info};

use crate::config::StorageConfig;

/// Storage service for database operations
#[derive(Clone)]
pub struct StorageService {
    pool: Pool<Sqlite>,
}

/// File metadata stored in database
#[derive(Debug, sqlx::FromRow, serde::Serialize)]
pub struct FileMetadata {
    pub id: i64,
    pub path: String,
    pub name: String,
    pub size: i64,
    pub mime_type: String,
    pub checksum: String,
    pub created_at: chrono::DateTime<chrono::Utc>,
    pub updated_at: chrono::DateTime<chrono::Utc>,
    pub tags: Option<String>,
    pub description: Option<String>,
}

/// File search metadata
#[derive(Debug, sqlx::FromRow)]
pub struct FileSearchData {
    pub path: String,
    pub content: String,
    pub embeddings: Option<Vec<u8>>,
}

impl StorageService {
    /// Create a new storage service
    pub async fn new(config: &StorageConfig) -> Result<Self> {
        info!("Connecting to database: {}", config.database_url);
        
        let pool = SqlitePool::connect(&config.database_url).await?;
        
        // Run migrations
        sqlx::migrate!("./migrations").run(&pool).await?;
        
        Ok(Self { pool })
    }

    /// Store file metadata
    pub async fn store_file_metadata(&self, metadata: &FileMetadata) -> Result<i64> {
        debug!("Storing file metadata: {}", metadata.path);
        
        let result = sqlx::query!(
            r#"
            INSERT INTO file_metadata (path, name, size, mime_type, checksum, tags, description)
            VALUES (?, ?, ?, ?, ?, ?, ?)
            ON CONFLICT(path) DO UPDATE SET
                name = excluded.name,
                size = excluded.size,
                mime_type = excluded.mime_type,
                checksum = excluded.checksum,
                tags = excluded.tags,
                description = excluded.description,
                updated_at = CURRENT_TIMESTAMP
            "#,
            metadata.path,
            metadata.name,
            metadata.size,
            metadata.mime_type,
            metadata.checksum,
            metadata.tags,
            metadata.description
        )
        .execute(&self.pool)
        .await?;

        Ok(result.last_insert_rowid())
    }

    /// Get file metadata by path
    pub async fn get_file_metadata(&self, path: &str) -> Result<Option<FileMetadata>> {
        debug!("Getting file metadata: {}", path);