Skip to content

Commit

Permalink
Refactor: create notification service module
Browse files Browse the repository at this point in the history
  • Loading branch information
zejiran committed Oct 12, 2023
1 parent 5a55655 commit 31bc1d5
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 74 deletions.
78 changes: 4 additions & 74 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,79 +1,9 @@
use std::collections::HashMap;
use std::time::{Duration, Instant};
use std::{collections::HashMap, time::Duration};

struct NotificationService {
rate_limits: HashMap<String, RateLimit>,
}

struct RateLimit {
max_requests: u32,
per_duration: Duration,
recipient_counters: HashMap<String, RecipientCounter>,
}

struct RecipientCounter {
allowed_requests: u32,
last_request: Option<Instant>,
}

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![
Expand All @@ -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(),
Expand Down
73 changes: 73 additions & 0 deletions src/notification_service.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use std::collections::HashMap;
use std::time::{Duration, Instant};

pub struct NotificationService {
pub rate_limits: HashMap<String, RateLimit>,
}

pub struct RateLimit {
pub max_requests: u32,
pub per_duration: Duration,
pub recipient_counters: HashMap<String, RecipientCounter>,
}

pub struct RecipientCounter {
allowed_requests: u32,
last_request: Option<Instant>,
}

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(())
}
}

0 comments on commit 31bc1d5

Please sign in to comment.