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