sombra/
error.rs

1//! Error handling for Sombra operations.
2//!
3//! This module defines the error types and handling utilities used
4//! throughout the Sombra graph database. All public APIs return
5//! `Result<T, GraphError>` for consistent error handling.
6//!
7//! # Error Types
8//!
9//! - [`GraphError`] - Main error enum with variants for different failure modes
10//! - [`Result`] - Result type alias for convenience
11//! - [`acquire_lock()`] - Helper for safe mutex locking
12//!
13//! # Error Handling Pattern
14//!
15//! ```rust
16//! use sombra::{GraphDB, Result};
17//!
18//! fn safe_operation() -> Result<()> {
19//!     let mut db = GraphDB::open("test.db")?;
20//!     let mut tx = db.begin_transaction()?;
21//!     // ... operations ...
22//!     tx.commit()?;
23//!     Ok(())
24//! }
25//! ```
26
27use std::io;
28use std::sync::{Mutex, MutexGuard};
29use thiserror::Error;
30use tracing::error;
31
32/// Result type for Sombra operations.
33///
34/// All public APIs return `Result<T, GraphError>` for error handling.
35pub type Result<T> = std::result::Result<T, GraphError>;
36
37/// Errors that can occur during database operations.
38///
39/// Sombra uses this comprehensive error type to handle all failure modes
40/// from I/O issues to data corruption to invalid usage.
41#[derive(Debug, Error)]
42pub enum GraphError {
43    /// I/O error from the underlying filesystem.
44    ///
45    /// This can occur during file operations like reading, writing,
46    /// or syncing data to disk.
47    #[error("I/O error: {0}")]
48    Io(#[from] io::Error),
49
50    /// Error during serialization or deserialization of data.
51    ///
52    /// This occurs when data cannot be properly encoded or decoded,
53    /// often due to format issues or buffer size problems.
54    #[error("serialization error: {0}")]
55    Serialization(String),
56
57    /// Data corruption detected.
58    ///
59    /// This is a critical error indicating that the database file
60    /// or WAL has been corrupted. It may be recoverable with the
61    /// repair tools, but data loss is possible.
62    #[error("corruption detected: {0}")]
63    Corruption(String),
64
65    /// Requested resource was not found.
66    ///
67    /// This occurs when trying to access a node or edge that doesn't
68    /// exist in the database.
69    #[error("{0} not found")]
70    NotFound(&'static str),
71
72    /// Invalid argument or operation.
73    ///
74    /// This occurs for various reasons:
75    /// - Invalid configuration parameters
76    /// - Operations that violate database constraints
77    /// - Transaction limits exceeded
78    /// - Invalid property types for indexing
79    #[error("invalid argument: {0}")]
80    InvalidArgument(String),
81
82    /// Feature is not yet implemented or supported.
83    ///
84    /// This indicates that the requested operation is not available
85    /// in the current version of Sombra.
86    #[error("unsupported feature: {0}")]
87    UnsupportedFeature(&'static str),
88}
89
90/// Safely acquires a mutex lock with proper error handling.
91///
92/// This helper function handles mutex poisoning errors that can occur
93/// when another thread panics while holding the lock. Instead of
94/// panicking, it converts the error to a `GraphError::Corruption`.
95///
96/// # Arguments
97/// * `mutex` - The mutex to lock
98///
99/// # Returns
100/// A `MutexGuard` on success, or `GraphError::Corruption` if the lock is poisoned.
101///
102/// # Safety
103/// This function is used throughout the codebase to ensure that lock
104/// poisoning is handled gracefully rather than causing panics.
105pub fn acquire_lock<T>(mutex: &Mutex<T>) -> Result<MutexGuard<'_, T>> {
106    mutex.lock().map_err(|_| {
107        error!("Database lock poisoned - fatal error");
108        GraphError::Corruption("Database lock poisoned - fatal error".into())
109    })
110}