Skip to main content

sui_cache/
lib.rs

1//! Built-in binary cache server and push pipeline for sui.
2//!
3//! Replaces Attic, Cachix, and nix-serve with a single integrated component.
4//! Implements the standard Nix binary cache HTTP protocol (narinfo + NAR).
5//!
6//! # Architecture
7//!
8//! - [`storage`] — pluggable storage backends (local filesystem, S3 stub)
9//! - [`server`] — axum HTTP server implementing the cache protocol
10//! - [`signing`] — ed25519 key management and narinfo signing
11//! - [`push`] — pipeline to push store paths to the cache
12//! - [`gc`] — garbage collection of unreferenced cache entries
13//! - [`config`] — cache configuration types
14
15pub mod config;
16pub mod gc;
17pub mod push;
18pub mod server;
19pub mod signing;
20pub mod storage;
21
22pub use config::{BackendConfig, CacheConfig};
23pub use gc::GcResult;
24pub use push::PushResult;
25pub use server::{build_router, serve, AppState};
26pub use signing::{verify_narinfo_signature, CacheSigner};
27pub use storage::{
28    build_backend, LocalStorage, PgCacheConn, PgStorageBackend, PgTable, RedisBackend, RedisConn,
29    S3Storage, StorageBackend, StorageIndex, TieredBackend, TieredTier, WritePolicy,
30    TIERED_BACKEND_TIER,
31};
32
33/// Errors from cache operations.
34#[derive(Debug, thiserror::Error)]
35pub enum CacheError {
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.
49    #[error("not implemented: {0}")]
50    NotImplemented(&'static str),
51
52    /// A narinfo could not be parsed.
53    #[error("narinfo error: {0}")]
54    NarInfo(String),
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60
61    #[test]
62    fn cache_error_display() {
63        let e = CacheError::PathNotFound("/nix/store/abc".to_string());
64        assert!(format!("{e}").contains("/nix/store/abc"));
65    }
66
67    #[test]
68    fn cache_error_io_display() {
69        let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "missing");
70        let e = CacheError::Io(io_err);
71        assert!(format!("{e}").contains("missing"));
72    }
73
74    #[test]
75    fn cache_error_signing_display() {
76        let e = CacheError::Signing("bad key".to_string());
77        assert!(format!("{e}").contains("bad key"));
78    }
79
80    #[test]
81    fn cache_error_not_implemented_display() {
82        let e = CacheError::NotImplemented("S3");
83        assert!(format!("{e}").contains("S3"));
84    }
85
86    #[test]
87    fn cache_error_narinfo_display() {
88        let e = CacheError::NarInfo("parse failed".to_string());
89        assert!(format!("{e}").contains("parse failed"));
90    }
91}