Skip to main content

hyperi_rustlib/io/
config.rs

1// Project:   hyperi-rustlib
2// File:      src/io/config.rs
3// Purpose:   Shared file writer configuration types
4// Language:  Rust
5//
6// License:   BUSL-1.1
7// Copyright: (c) 2026 HYPERI PTY LIMITED
8
9//! Shared configuration for NDJSON file writers.
10//!
11//! Used by both the DLQ file backend and the file output sink.
12
13use std::path::PathBuf;
14
15use serde::{Deserialize, Serialize};
16
17/// File rotation period.
18#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
19#[serde(rename_all = "snake_case")]
20pub enum RotationPeriod {
21    /// Rotate files every hour.
22    #[default]
23    Hourly,
24    /// Rotate files every day.
25    Daily,
26}
27
28/// Shared file writer configuration.
29///
30/// Contains the core settings for rotating NDJSON file output. Used by
31/// [`super::NdjsonWriter`] and consumed by both DLQ and file output modules.
32#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct FileWriterConfig {
34    /// Base directory for output files.
35    pub path: PathBuf,
36
37    /// File rotation period.
38    pub rotation: RotationPeriod,
39
40    /// Auto-cleanup files older than this many days.
41    pub max_age_days: u32,
42
43    /// Compress rotated files with flate2/gzip.
44    pub compress_rotated: bool,
45}
46
47impl Default for FileWriterConfig {
48    fn default() -> Self {
49        Self {
50            path: PathBuf::from("/var/spool/dfe"),
51            rotation: RotationPeriod::default(),
52            max_age_days: 30,
53            compress_rotated: true,
54        }
55    }
56}
57
58#[cfg(test)]
59mod tests {
60    use super::*;
61
62    #[test]
63    fn test_defaults() {
64        let config = FileWriterConfig::default();
65        assert_eq!(config.path, PathBuf::from("/var/spool/dfe"));
66        assert_eq!(config.rotation, RotationPeriod::Hourly);
67        assert_eq!(config.max_age_days, 30);
68        assert!(config.compress_rotated);
69    }
70
71    #[test]
72    fn test_rotation_period_serde() {
73        let json = r#""hourly""#;
74        let period: RotationPeriod = serde_json::from_str(json).expect("deserialise");
75        assert_eq!(period, RotationPeriod::Hourly);
76
77        let json = r#""daily""#;
78        let period: RotationPeriod = serde_json::from_str(json).expect("deserialise");
79        assert_eq!(period, RotationPeriod::Daily);
80    }
81
82    #[test]
83    fn test_config_serde_roundtrip() {
84        let config = FileWriterConfig {
85            path: "/tmp/test".into(),
86            rotation: RotationPeriod::Daily,
87            max_age_days: 7,
88            compress_rotated: false,
89        };
90        let json = serde_json::to_string(&config).expect("serialise");
91        let parsed: FileWriterConfig = serde_json::from_str(&json).expect("deserialise");
92        assert_eq!(parsed.path, PathBuf::from("/tmp/test"));
93        assert_eq!(parsed.rotation, RotationPeriod::Daily);
94        assert_eq!(parsed.max_age_days, 7);
95        assert!(!parsed.compress_rotated);
96    }
97}