postfix_log_parser/components/
postsuper.rs1
2use crate::components::ComponentParser;
34use crate::error::ParseError;
35use crate::events::{ComponentEvent, PostsuperEvent};
36use chrono::Utc;
37use regex::Regex;
38
39pub struct PostsuperParser {
41 message_removed_regex: Regex,
43 bulk_deleted_regex: Regex,
45}
46
47impl PostsuperParser {
48 pub fn new() -> Result<Self, ParseError> {
50 let message_removed_regex =
51 Regex::new(r"^([A-F0-9]+):\s*removed\s*$").map_err(ParseError::RegexError)?;
52
53 let bulk_deleted_regex =
54 Regex::new(r"^Deleted:\s*(\d+)\s*messages?\s*$").map_err(ParseError::RegexError)?;
55
56 Ok(Self {
57 message_removed_regex,
58 bulk_deleted_regex,
59 })
60 }
61
62 fn parse_message_removed(&self, message: &str) -> Option<PostsuperEvent> {
64 if let Some(caps) = self.message_removed_regex.captures(message) {
65 let queue_id = caps.get(1)?.as_str().to_string();
66 return Some(PostsuperEvent::message_removed(Utc::now(), queue_id));
67 }
68 None
69 }
70
71 fn parse_bulk_deleted(&self, message: &str) -> Option<PostsuperEvent> {
73 if let Some(caps) = self.bulk_deleted_regex.captures(message) {
74 let count_str = caps.get(1)?.as_str();
75 if let Ok(count) = count_str.parse::<u32>() {
76 return Some(PostsuperEvent::bulk_deleted(Utc::now(), count));
77 }
78 }
79 None
80 }
81}
82
83impl ComponentParser for PostsuperParser {
84 fn parse(&self, message: &str) -> Result<ComponentEvent, ParseError> {
85 if let Some(event) = self.parse_message_removed(message) {
87 return Ok(ComponentEvent::Postsuper(event));
88 }
89
90 if let Some(event) = self.parse_bulk_deleted(message) {
92 return Ok(ComponentEvent::Postsuper(event));
93 }
94
95 Err(ParseError::ComponentParseError {
97 component: "postsuper".to_string(),
98 reason: format!("Unknown message format: {}", message),
99 })
100 }
101
102 fn component_name(&self) -> &'static str {
103 "postsuper"
104 }
105
106 fn can_parse(&self, message: &str) -> bool {
107 self.message_removed_regex.is_match(message) || self.bulk_deleted_regex.is_match(message)
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114
115 #[test]
116 fn test_parse_message_removed() {
117 let parser = PostsuperParser::new().unwrap();
118
119 let message = "61563640322461696: removed";
121 let result = parser.parse(message).unwrap();
122
123 if let ComponentEvent::Postsuper(event) = result {
124 assert_eq!(
125 event.event_type,
126 crate::events::postsuper::PostsuperEventType::MessageRemoved
127 );
128 assert_eq!(event.queue_id, Some("61563640322461696".to_string()));
129 assert_eq!(event.description, Some("removed".to_string()));
130 } else {
131 panic!("Expected PostsuperEvent::MessageRemoved");
132 }
133 }
134
135 #[test]
136 fn test_parse_bulk_deleted() {
137 let parser = PostsuperParser::new().unwrap();
138
139 let message = "Deleted: 1 message";
141 let result = parser.parse(message).unwrap();
142
143 if let ComponentEvent::Postsuper(event) = result {
144 assert_eq!(
145 event.event_type,
146 crate::events::postsuper::PostsuperEventType::BulkDeleted
147 );
148 assert_eq!(event.message_count, Some(1));
149 assert_eq!(event.description, Some("Deleted: 1 message".to_string()));
150 } else {
151 panic!("Expected PostsuperEvent::BulkDeleted");
152 }
153 }
154
155 #[test]
156 fn test_parse_bulk_deleted_multiple() {
157 let parser = PostsuperParser::new().unwrap();
158
159 let message = "Deleted: 5 messages";
161 let result = parser.parse(message).unwrap();
162
163 if let ComponentEvent::Postsuper(event) = result {
164 assert_eq!(
165 event.event_type,
166 crate::events::postsuper::PostsuperEventType::BulkDeleted
167 );
168 assert_eq!(event.message_count, Some(5));
169 assert_eq!(event.description, Some("Deleted: 5 messages".to_string()));
170 } else {
171 panic!("Expected PostsuperEvent::BulkDeleted");
172 }
173 }
174
175 #[test]
176 fn test_can_parse() {
177 let parser = PostsuperParser::new().unwrap();
178
179 assert!(parser.can_parse("61563640322461696: removed"));
180 assert!(parser.can_parse("Deleted: 1 message"));
181 assert!(parser.can_parse("Deleted: 10 messages"));
182 assert!(!parser.can_parse("some other message"));
183 }
184}