Skip to main content

hyperi_rustlib/spool/
config.rs

1// Project:   hyperi-rustlib
2// File:      src/spool/config.rs
3// Purpose:   Spool configuration
4// Language:  Rust
5//
6// License:   BUSL-1.1
7// Copyright: (c) 2026 HYPERI PTY LIMITED
8
9//! Spool configuration.
10
11use serde::{Deserialize, Serialize};
12use std::path::PathBuf;
13
14/// Configuration for the disk-backed spool.
15#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct SpoolConfig {
17    /// Path to the queue file.
18    pub path: PathBuf,
19
20    /// Enable zstd compression for stored items.
21    /// Reduces disk usage at the cost of CPU.
22    /// Defaults to false.
23    #[serde(default)]
24    pub compress: bool,
25
26    /// Zstd compression level (1-22, higher = better compression, slower).
27    /// Only used if `compress` is true.
28    /// Defaults to 3 (fast compression).
29    #[serde(default = "default_compression_level")]
30    pub compression_level: i32,
31
32    /// Maximum number of items in the queue.
33    /// If set, push operations will fail when the limit is reached.
34    /// Defaults to None (unlimited).
35    #[serde(default)]
36    pub max_items: Option<usize>,
37
38    /// Maximum total size of the queue file in bytes.
39    /// If set, push operations will fail when the limit is reached.
40    /// Defaults to None (unlimited).
41    #[serde(default)]
42    pub max_size_bytes: Option<u64>,
43}
44
45fn default_compression_level() -> i32 {
46    3
47}
48
49impl Default for SpoolConfig {
50    fn default() -> Self {
51        Self {
52            path: PathBuf::from("spool.queue"),
53            compress: false,
54            compression_level: default_compression_level(),
55            max_items: None,
56            max_size_bytes: None,
57        }
58    }
59}
60
61impl SpoolConfig {
62    /// Create a new config with the given path.
63    #[must_use]
64    pub fn new(path: impl Into<PathBuf>) -> Self {
65        Self {
66            path: path.into(),
67            ..Default::default()
68        }
69    }
70
71    /// Create a config with compression enabled.
72    #[must_use]
73    pub fn with_compression(path: impl Into<PathBuf>) -> Self {
74        Self {
75            path: path.into(),
76            compress: true,
77            ..Default::default()
78        }
79    }
80
81    /// Set whether compression is enabled.
82    #[must_use]
83    pub fn compress(mut self, enabled: bool) -> Self {
84        self.compress = enabled;
85        self
86    }
87
88    /// Set the compression level (1-22).
89    #[must_use]
90    pub fn compression_level(mut self, level: i32) -> Self {
91        self.compression_level = level.clamp(1, 22);
92        self
93    }
94
95    /// Set the maximum number of items.
96    #[must_use]
97    pub fn max_items(mut self, max: usize) -> Self {
98        self.max_items = Some(max);
99        self
100    }
101
102    /// Set the maximum queue file size in bytes.
103    #[must_use]
104    pub fn max_size_bytes(mut self, max: u64) -> Self {
105        self.max_size_bytes = Some(max);
106        self
107    }
108}
109
110#[cfg(test)]
111mod tests {
112    use super::*;
113
114    #[test]
115    fn test_default_config() {
116        let config = SpoolConfig::default();
117        assert_eq!(config.path, PathBuf::from("spool.queue"));
118        assert!(!config.compress);
119        assert_eq!(config.compression_level, 3);
120        assert!(config.max_items.is_none());
121        assert!(config.max_size_bytes.is_none());
122    }
123
124    #[test]
125    fn test_new_with_path() {
126        let config = SpoolConfig::new("/tmp/test.queue");
127        assert_eq!(config.path, PathBuf::from("/tmp/test.queue"));
128    }
129
130    #[test]
131    fn test_with_compression() {
132        let config = SpoolConfig::with_compression("/tmp/test.queue");
133        assert!(config.compress);
134    }
135
136    #[test]
137    fn test_builder_pattern() {
138        let config = SpoolConfig::new("/tmp/test.queue")
139            .compress(true)
140            .compression_level(10)
141            .max_items(1000)
142            .max_size_bytes(1024 * 1024);
143
144        assert!(config.compress);
145        assert_eq!(config.compression_level, 10);
146        assert_eq!(config.max_items, Some(1000));
147        assert_eq!(config.max_size_bytes, Some(1024 * 1024));
148    }
149
150    #[test]
151    fn test_compression_level_clamped() {
152        let config = SpoolConfig::default().compression_level(100);
153        assert_eq!(config.compression_level, 22);
154
155        let config = SpoolConfig::default().compression_level(-5);
156        assert_eq!(config.compression_level, 1);
157    }
158}