Skip to main content

nexus_memory_storage/
lib.rs

1//! Nexus Storage - Database operations and storage layer
2//!
3//! This crate provides SQLite-based storage using SQLx.
4
5pub mod migrations;
6pub mod models;
7pub mod repository;
8
9pub use migrations::create_processed_files_table;
10pub use models::*;
11pub use repository::{
12    ListMemoryFilters, MemoryRelationRepository, MemoryRepository, MetricSample,
13    NamespaceRepository, ProcessedFileRepository, SemanticCandidateParams, StoreDigestParams,
14    StoreMemoryParams, StoreMemoryWithLineageParams, WorkingSetParams,
15};
16
17use sqlx::sqlite::SqliteConnectOptions;
18use sqlx::SqlitePool;
19
20/// Convert sqlx::Error to NexusError
21pub fn db_error(err: sqlx::Error) -> nexus_core::NexusError {
22    nexus_core::NexusError::Database(err.to_string())
23}
24
25/// Storage manager for database operations
26pub struct StorageManager {
27    pool: SqlitePool,
28    initialized: bool,
29}
30
31impl StorageManager {
32    /// Create a new storage manager
33    pub fn new(pool: SqlitePool) -> Self {
34        Self {
35            pool,
36            initialized: false,
37        }
38    }
39
40    /// Create a new storage manager from database URL
41    pub async fn from_url(url: &str) -> crate::Result<Self> {
42        let options = url
43            .parse::<SqliteConnectOptions>()
44            .map_err(|err| nexus_core::NexusError::Database(err.to_string()))?
45            .create_if_missing(true)
46            .journal_mode(sqlx::sqlite::SqliteJournalMode::Wal)
47            .busy_timeout(std::time::Duration::from_secs(5))
48            .synchronous(sqlx::sqlite::SqliteSynchronous::Normal)
49            // Per-connection pragmas — these are applied to every pooled connection.
50            .foreign_keys(true)
51            .pragma("cache_size", "-2000")
52            .pragma("temp_store", "MEMORY");
53
54        let pool = SqlitePool::connect_with(options).await.map_err(db_error)?;
55
56        Ok(Self::new(pool))
57    }
58
59    /// Initialize the database schema
60    pub async fn initialize(&mut self) -> crate::Result<()> {
61        if self.initialized {
62            return Ok(());
63        }
64
65        migrations::run_migrations(&self.pool).await?;
66        self.initialized = true;
67        Ok(())
68    }
69
70    /// Get a reference to the connection pool
71    pub fn pool(&self) -> &SqlitePool {
72        &self.pool
73    }
74
75    /// Check if initialized
76    pub fn is_initialized(&self) -> bool {
77        self.initialized
78    }
79}
80
81pub type Result<T> = std::result::Result<T, nexus_core::NexusError>;