Skip to main content

sui_castore/
lib.rs

1//! Content-addressed store backends for sui.
2//!
3//! This crate owns the [`StorageBackend`] trait and every concrete
4//! implementation (Local / S3 / Redis / Postgres / Tiered), plus the
5//! [`BackendConfig`] config-select enum and the [`build_backend`] factory.
6//! Both `sui-cache` (the Nix binary-cache server) and `sui-registry` (the OCI
7//! registry `porto`) depend on this crate; neither depends on the other.
8//!
9//! # Feature flags
10//!
11//! - **`redis-client`** — enables the production [`RedisConnectionManager`]
12//!   transport. Without it the Redis arm of [`build_backend`] returns a typed
13//!   [`StoreError::NotImplemented`].
14//! - **`postgres`** — enables the production [`SqlxPgCacheConn`] transport.
15//!   Without it the Postgres arm returns [`StoreError::NotImplemented`].
16
17pub mod config;
18pub mod storage;
19
20pub use config::BackendConfig;
21pub use storage::{
22    build_backend, LocalStorage, PgCacheConn, PgStorageBackend, PgTable, RedisBackend, RedisConn,
23    S3Storage, StorageBackend, StorageIndex, TieredBackend, TieredTier, WritePolicy,
24    TIERED_BACKEND_TIER,
25};
26
27#[cfg(feature = "redis-client")]
28pub use storage::RedisConnectionManager;
29
30#[cfg(feature = "postgres")]
31pub use storage::SqlxPgCacheConn;
32
33/// Error type for content-addressed store operations.
34#[derive(Debug, thiserror::Error)]
35pub enum StoreError {
36    /// An I/O operation failed.
37    #[error("io error: {0}")]
38    Io(#[from] std::io::Error),
39
40    /// A store path was not found on the local filesystem.
41    #[error("path not found: {0}")]
42    PathNotFound(String),
43
44    /// A signing or verification operation failed.
45    #[error("signing error: {0}")]
46    Signing(String),
47
48    /// A feature is not yet implemented (missing Cargo feature flag).
49    #[error("not implemented: {0}")]
50    NotImplemented(&'static str),
51
52    /// A narinfo could not be parsed or was invalid UTF-8.
53    #[error("narinfo error: {0}")]
54    NarInfo(String),
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60
61    #[test]
62    fn store_error_display_path_not_found() {
63        let e = StoreError::PathNotFound("/nix/store/abc".to_string());
64        assert!(format!("{e}").contains("/nix/store/abc"));
65    }
66
67    #[test]
68    fn store_error_display_io() {
69        let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "missing");
70        let e = StoreError::Io(io_err);
71        assert!(format!("{e}").contains("missing"));
72    }
73
74    #[test]
75    fn store_error_display_signing() {
76        let e = StoreError::Signing("bad key".to_string());
77        assert!(format!("{e}").contains("bad key"));
78    }
79
80    #[test]
81    fn store_error_display_not_implemented() {
82        let e = StoreError::NotImplemented("redis L1");
83        assert!(format!("{e}").contains("redis L1"));
84    }
85
86    #[test]
87    fn store_error_display_narinfo() {
88        let e = StoreError::NarInfo("parse failed".to_string());
89        assert!(format!("{e}").contains("parse failed"));
90    }
91}