1use serde::{Deserialize, Serialize};
11use validator::Validate;
12
13#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
18pub struct EventsConfig {
19 #[serde(default)]
24 pub enabled: bool,
25
26 #[serde(default)]
28 #[validate(nested)]
29 pub batching: BatchingConfig,
30
31 #[serde(default = "default_channel_capacity")]
36 #[validate(range(min = 16, max = 65536))]
37 pub channel_capacity: usize,
38
39 #[serde(default = "default_subject")]
44 pub subject: String,
45
46 #[serde(default)]
52 pub policy: EventPolicyConfig,
53}
54
55impl Default for EventsConfig {
56 fn default() -> Self {
57 Self {
58 enabled: false,
59 batching: BatchingConfig::default(),
60 channel_capacity: default_channel_capacity(),
61 subject: default_subject(),
62 policy: EventPolicyConfig::default(),
63 }
64 }
65}
66
67fn default_channel_capacity() -> usize {
68 1024
69}
70
71fn default_subject() -> String {
72 "kvbm.events".to_string()
73}
74
75#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
83pub struct BatchingConfig {
84 #[serde(default = "default_window_duration_ms")]
88 #[validate(range(min = 1, max = 10000))]
89 pub window_duration_ms: u64,
90
91 #[serde(default = "default_max_batch_size")]
95 #[validate(range(min = 1, max = 65536))]
96 pub max_batch_size: usize,
97}
98
99impl Default for BatchingConfig {
100 fn default() -> Self {
101 Self {
102 window_duration_ms: default_window_duration_ms(),
103 max_batch_size: default_max_batch_size(),
104 }
105 }
106}
107
108fn default_window_duration_ms() -> u64 {
109 10
110}
111
112fn default_max_batch_size() -> usize {
113 1024
114}
115
116#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
118#[serde(rename_all = "snake_case")]
119pub enum EventPolicyConfig {
120 #[default]
125 PowerOfTwo,
126
127 All,
131}
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136
137 #[test]
138 fn test_default_config() {
139 let config = EventsConfig::default();
140 assert!(!config.enabled);
141 assert_eq!(config.batching.window_duration_ms, 10);
142 assert_eq!(config.batching.max_batch_size, 1024);
143 assert_eq!(config.channel_capacity, 1024);
144 assert_eq!(config.subject, "kvbm.events");
145 assert_eq!(config.policy, EventPolicyConfig::PowerOfTwo);
146 }
147
148 #[test]
149 fn test_serde_roundtrip() {
150 let json = r#"{
151 "enabled": true,
152 "batching": {
153 "window_duration_ms": 50,
154 "max_batch_size": 512
155 },
156 "channel_capacity": 2048,
157 "subject": "my.events",
158 "policy": "all"
159 }"#;
160
161 let config: EventsConfig = serde_json::from_str(json).unwrap();
162 assert!(config.enabled);
163 assert_eq!(config.batching.window_duration_ms, 50);
164 assert_eq!(config.batching.max_batch_size, 512);
165 assert_eq!(config.channel_capacity, 2048);
166 assert_eq!(config.subject, "my.events");
167 assert_eq!(config.policy, EventPolicyConfig::All);
168
169 let serialized = serde_json::to_string(&config).unwrap();
171 let deserialized: EventsConfig = serde_json::from_str(&serialized).unwrap();
172 assert_eq!(deserialized.enabled, config.enabled);
173 assert_eq!(deserialized.policy, config.policy);
174 }
175
176 #[test]
177 fn test_empty_json_uses_defaults() {
178 let json = r#"{}"#;
179 let config: EventsConfig = serde_json::from_str(json).unwrap();
180 assert!(!config.enabled);
181 assert_eq!(config.batching.window_duration_ms, 10);
182 }
183
184 #[test]
185 fn test_partial_config() {
186 let json = r#"{"enabled": true}"#;
188 let config: EventsConfig = serde_json::from_str(json).unwrap();
189 assert!(config.enabled);
190 assert_eq!(config.batching.window_duration_ms, 10);
191 assert_eq!(config.channel_capacity, 1024);
192 }
193
194 #[test]
195 fn test_validation() {
196 let config = EventsConfig {
197 enabled: true,
198 batching: BatchingConfig {
199 window_duration_ms: 10,
200 max_batch_size: 1024,
201 },
202 channel_capacity: 1024,
203 subject: "test".to_string(),
204 policy: EventPolicyConfig::PowerOfTwo,
205 };
206 assert!(config.validate().is_ok());
207 }
208}