Skip to main content

genegraph_storage/
lib.rs

1#![allow(async_fn_in_trait)]
2pub mod catalog;
3pub mod commit;
4pub mod generations;
5pub mod graph;
6#[cfg(feature = "arrow-ipc")]
7pub mod ipc;
8pub mod lance_storage_graph;
9pub mod lancefmt;
10pub mod metadata;
11pub mod traits;
12pub mod zarr_storage;
13pub mod zzarr;
14
15#[cfg(all(test, unix))]
16mod tests;
17
18use std::fmt;
19
20// Error Handling harness
21//
22// `#[non_exhaustive]` lets this crate add error variants in future releases
23// without breaking downstream `match` expressions that carry a wildcard arm.
24#[derive(Debug)]
25#[non_exhaustive]
26pub enum StorageError {
27    Io(String),
28    Serde(serde_json::Error),
29    Parquet(String),
30    Invalid(String),
31    Lance(String),
32    QueryError(String),
33    /// A storage resource is in an unexpected state (e.g. the metadata path
34    /// passed to a `save_*` call does not match the instance metadata path).
35    InvalidState(String),
36    /// A filetype does not map to a known storage format.
37    UnsupportedFormat(String),
38    /// An Arrow-IPC codec error (#142): file/stream write, read or schema
39    /// mismatch surfaced by the `arrow-ipc` writer/reader.
40    IPC(String),
41    /// A key/filetype is not recognised as one of the supported file types.
42    UnsupportedFiletype(String),
43    /// Dimensions recorded in schema metadata do not match the dimensions
44    /// recorded in storage metadata.
45    DimensionMismatch {
46        expected: String,
47        found: String,
48    },
49    /// A numeric value exceeds the range of the storage type it is written to.
50    Overflow(String),
51    /// A non-blocking lock acquisition would block: the advisory lock file
52    /// is held by another cooperating writer. Distinctly matchable so
53    /// fail-fast consumers can map contention to their own taxonomy (#105).
54    LockWouldBlock {
55        path: std::path::PathBuf,
56    },
57}
58
59impl fmt::Display for StorageError {
60    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61        match self {
62            StorageError::Io(msg) => write!(f, "IO error: {}", msg),
63            StorageError::Serde(msg) => write!(f, "Serialization error: {}", msg),
64            StorageError::Parquet(msg) => write!(f, "Parquet error: {}", msg),
65            StorageError::Invalid(msg) => write!(f, "Invalid data: {}", msg),
66            StorageError::Lance(msg) => write!(f, "Lance error: {}", msg),
67            StorageError::QueryError(msg) => write!(f, "Query error: {}", msg),
68            StorageError::InvalidState(msg) => write!(f, "Invalid state: {}", msg),
69            StorageError::UnsupportedFormat(msg) => write!(f, "Unsupported format: {}", msg),
70            StorageError::IPC(msg) => write!(f, "Arrow IPC error: {}", msg),
71            StorageError::UnsupportedFiletype(msg) => write!(f, "Unsupported filetype: {}", msg),
72            StorageError::DimensionMismatch { expected, found } => {
73                write!(
74                    f,
75                    "Dimension mismatch: expected {}, found {}",
76                    expected, found
77                )
78            }
79            StorageError::Overflow(msg) => write!(f, "Overflow error: {}", msg),
80            StorageError::LockWouldBlock { path } => {
81                write!(
82                    f,
83                    "Lock would block: {} is held by another holder",
84                    path.display()
85                )
86            }
87        }
88    }
89}
90
91impl std::error::Error for StorageError {}
92
93pub type StorageResult<T> = Result<T, StorageError>;
94
95// Logging harness
96use std::sync::Once;
97
98static INIT: Once = Once::new();
99
100pub fn init() {
101    INIT.call_once(|| {
102        // Read RUST_LOG env variable, default to "info" if not set
103        let env = env_logger::Env::default().default_filter_or("info");
104
105        // don't panic if called multiple times across binaries
106        let _ = env_logger::Builder::from_env(env).try_init();
107    });
108}