diff --git a/src/main.rs b/src/main.rs index c9e9abc..ff58da3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,79 +1,9 @@ -use std::collections::HashMap; -use std::time::{Duration, Instant}; +use std::{collections::HashMap, time::Duration}; -struct NotificationService { - rate_limits: HashMap, -} - -struct RateLimit { - max_requests: u32, - per_duration: Duration, - recipient_counters: HashMap, -} - -struct RecipientCounter { - allowed_requests: u32, - last_request: Option, -} - -impl NotificationService { - fn new() -> Self { - NotificationService { - rate_limits: HashMap::new(), - } - } - - fn send( - &mut self, - notification_type: &str, - recipient: &str, - message: &str, - ) -> Result<(), String> { - let rate_limit = self - .rate_limits - .entry(notification_type.to_string()) - .or_insert(RateLimit { - max_requests: u32::MAX, - per_duration: Duration::from_secs(1), - recipient_counters: HashMap::new(), - }); - - let recipient_counter = rate_limit - .recipient_counters - .entry(recipient.to_string()) - .or_insert(RecipientCounter { - allowed_requests: rate_limit.max_requests, - last_request: Some(Instant::now()), - }); - - let now = Instant::now(); - let elapsed = now.duration_since(recipient_counter.last_request.unwrap_or(now)); - - if elapsed <= rate_limit.per_duration { - if recipient_counter.allowed_requests <= 0 { - return Err(format!( - "Rate limit exceeded for {} notifications to {}. No more requests allowed.", - notification_type, recipient - )); - } - recipient_counter.allowed_requests -= 1; - } else { - recipient_counter.last_request = Some(now); - recipient_counter.allowed_requests = rate_limit.max_requests - 1; - } - - // Perform the actual notification sending here. - println!( - "Sending {} notification to {}: {}", - notification_type, recipient, message - ); - - Ok(()) - } -} +mod notification_service; fn main() { - let mut service = NotificationService::new(); + let mut service = notification_service::NotificationService::new(); // Define rate limits for different notification types let rate_limits = vec![ @@ -85,7 +15,7 @@ fn main() { for (notification_type, max_requests, per_duration) in rate_limits { service.rate_limits.insert( notification_type.to_string(), - RateLimit { + notification_service::RateLimit { max_requests, per_duration, recipient_counters: HashMap::new(), diff --git a/src/notification_service.rs b/src/notification_service.rs new file mode 100644 index 0000000..8ad0ca3 --- /dev/null +++ b/src/notification_service.rs @@ -0,0 +1,73 @@ +use std::collections::HashMap; +use std::time::{Duration, Instant}; + +pub struct NotificationService { + pub rate_limits: HashMap, +} + +pub struct RateLimit { + pub max_requests: u32, + pub per_duration: Duration, + pub recipient_counters: HashMap, +} + +pub struct RecipientCounter { + allowed_requests: u32, + last_request: Option, +} + +impl NotificationService { + pub fn new() -> Self { + NotificationService { + rate_limits: HashMap::new(), + } + } + + pub fn send( + &mut self, + notification_type: &str, + recipient: &str, + message: &str, + ) -> Result<(), String> { + let rate_limit = self + .rate_limits + .entry(notification_type.to_string()) + .or_insert(RateLimit { + max_requests: u32::MAX, + per_duration: Duration::from_secs(1), + recipient_counters: HashMap::new(), + }); + + let recipient_counter = rate_limit + .recipient_counters + .entry(recipient.to_string()) + .or_insert(RecipientCounter { + allowed_requests: rate_limit.max_requests, + last_request: Some(Instant::now()), + }); + + let now = Instant::now(); + let elapsed = now.duration_since(recipient_counter.last_request.unwrap_or(now)); + + if elapsed <= rate_limit.per_duration { + if recipient_counter.allowed_requests <= 0 { + return Err(format!( + "Rate limit exceeded for {} notifications to {}. No more requests allowed.", + notification_type, recipient + )); + } + recipient_counter.allowed_requests -= 1; + } else { + recipient_counter.last_request = Some(now); + recipient_counter.allowed_requests = rate_limit.max_requests - 1; + } + + // Perform the actual notification sending here. + println!( + "Sending {} notification to {}: {}", + notification_type, recipient, message + ); + + Ok(()) + } +}