Skip to main content

sui_cache/
config.rs

1//! Cache configuration types.
2
3use std::path::PathBuf;
4
5use serde::{Deserialize, Serialize};
6
7/// Top-level cache configuration.
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct CacheConfig {
10    /// Network address to listen on.
11    pub listen: String,
12    /// Storage backend configuration.
13    pub backend: BackendConfig,
14    /// Path to the ed25519 signing secret key file.
15    pub signing_key: Option<PathBuf>,
16    /// Cache priority (lower = preferred). Reported in nix-cache-info.
17    pub priority: u32,
18    /// Whether to want mass query (narinfo pipelining).
19    pub want_mass_query: bool,
20    /// The Nix store directory (almost always `/nix/store`).
21    pub store_dir: String,
22}
23
24impl Default for CacheConfig {
25    fn default() -> Self {
26        Self {
27            listen: "0.0.0.0:5000".to_string(),
28            backend: BackendConfig::default(),
29            signing_key: None,
30            priority: 40,
31            want_mass_query: true,
32            store_dir: "/nix/store".to_string(),
33        }
34    }
35}
36
37/// Storage backend selection.
38#[derive(Debug, Clone, Serialize, Deserialize)]
39#[serde(tag = "type", rename_all = "lowercase")]
40pub enum BackendConfig {
41    /// Local filesystem storage.
42    Local {
43        /// Root directory for NAR and narinfo files.
44        path: PathBuf,
45    },
46    /// S3-compatible object storage (stub).
47    S3 {
48        bucket: String,
49        region: String,
50        endpoint: Option<String>,
51    },
52}
53
54impl Default for BackendConfig {
55    fn default() -> Self {
56        Self::Local {
57            path: PathBuf::from("/var/cache/sui"),
58        }
59    }
60}
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65
66    #[test]
67    fn default_config_has_sane_values() {
68        let config = CacheConfig::default();
69        assert_eq!(config.listen, "0.0.0.0:5000");
70        assert_eq!(config.store_dir, "/nix/store");
71        assert_eq!(config.priority, 40);
72        assert!(config.want_mass_query);
73        assert!(config.signing_key.is_none());
74    }
75
76    #[test]
77    fn default_backend_is_local() {
78        let config = CacheConfig::default();
79        assert!(matches!(config.backend, BackendConfig::Local { .. }));
80    }
81
82    #[test]
83    fn config_serializes_to_json() {
84        let config = CacheConfig::default();
85        let json = serde_json::to_string(&config).unwrap();
86        assert!(json.contains("local"));
87        assert!(json.contains("5000"));
88    }
89
90    #[test]
91    fn config_roundtrips_through_json() {
92        let config = CacheConfig {
93            listen: "127.0.0.1:8080".to_string(),
94            backend: BackendConfig::S3 {
95                bucket: "my-cache".to_string(),
96                region: "us-east-1".to_string(),
97                endpoint: Some("http://localhost:9000".to_string()),
98            },
99            signing_key: Some(PathBuf::from("/tmp/key.sec")),
100            priority: 30,
101            want_mass_query: false,
102            store_dir: "/nix/store".to_string(),
103        };
104        let json = serde_json::to_string_pretty(&config).unwrap();
105        let parsed: CacheConfig = serde_json::from_str(&json).unwrap();
106        assert_eq!(parsed.listen, "127.0.0.1:8080");
107        assert_eq!(parsed.priority, 30);
108        assert!(!parsed.want_mass_query);
109        assert!(matches!(parsed.backend, BackendConfig::S3 { .. }));
110    }
111}