use crate::store::STORE_TABLE; use redb::{Database, ReadableTable}; use std::path::Path; use std::sync::Arc; pub fn init_redb(base: &Path) -> Arc { let redb_path = base.join("mcp_store.redb"); let db = match redb::Database::create(&redb_path) { Ok(db) => Arc::new(db), Err(e) => { let err_msg = format!( "Failed to open or create redb database at {:?}: {}. Falling back to temporary store.", redb_path, e ); tracing::error!("{}", err_msg); let temp_path = std::env::temp_dir().join(format!("mcp_store_fallback_{}.redb", uuid::Uuid::new_v4())); Arc::new(redb::Database::create(&temp_path).expect("Failed to create fallback redb database")) } }; // Ensure the table exists and migrate legacy JSON files match db.begin_write() { Ok(write_txn) => { let mut opened_ok = false; if let Ok(mut table) = write_txn.open_table(STORE_TABLE) { opened_ok = true; let stores = vec![ ("knowledge_graph_master", "knowledge_graph_master.json"), ("audit_ledger", "audit_ledger.json"), ("sticky_notes", "sticky_notes.json"), ("tasks", "tasks.json"), ("snippets", "snippets.json"), ("adrs", "adrs.json"), ("preferences", "preferences.json"), ("error_fixes", "error_fixes.json"), ("pinned_files", "pinned_files.json"), ("session_summaries", "session_summaries.json"), ("handoff_memos", "handoff_memos.json"), ("env_fingerprints", "env_fingerprints.json"), ("env_requirements", "env_requirements.json"), ("milestones", "milestones.json"), ("environments", "environments.json"), ("pr_checklists", "pr_checklists.json"), ("tech_debts", "tech_debts.json"), ("gates", "gates.json"), ("context_workspaces", "context_workspaces.json"), ]; for (key, file_name) in stores.iter() { let is_missing = match table.get(*key) { Ok(res) => res.is_none(), Err(e) => { tracing::warn!("Failed to read key '{}' from redb: {}", key, e); false } }; if is_missing { let json_path = base.join(file_name); if json_path.exists() && let Ok(data) = std::fs::read(&json_path) && serde_json::from_slice::(&data).is_ok() { if let Err(e) = table.insert(*key, data.as_slice()) { tracing::error!("Failed to insert migrated key '{}': {}", key, e); } else { let _ = std::fs::rename(&json_path, json_path.with_extension("json.migrated")); } } } } } if opened_ok { if let Err(e) = write_txn.commit() { tracing::error!("Failed to commit database migration transaction: {}", e); } } } Err(e) => { tracing::error!("Failed to begin write transaction for redb migration: {}", e); } } db }