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}