use std::env;
use std::time::Duration;
#[derive(Debug, Clone)]
pub struct QueueConfig {
pub default_queue: String,
pub max_concurrent_jobs: usize,
pub sleep_duration: Duration,
pub visibility_timeout: Duration,
}
impl Default for QueueConfig {
fn default() -> Self {
Self {
default_queue: "default".to_string(),
max_concurrent_jobs: 10,
sleep_duration: Duration::from_millis(500),
visibility_timeout: Duration::from_secs(300),
}
}
}
impl QueueConfig {
pub fn from_env() -> Self {
Self {
default_queue: env::var("QUEUE_DEFAULT").unwrap_or_else(|_| "default".to_string()),
max_concurrent_jobs: env::var("QUEUE_MAX_CONCURRENT")
.ok()
.and_then(|v| v.parse().ok())
.unwrap_or(10),
sleep_duration: Duration::from_millis(500),
visibility_timeout: Duration::from_secs(
env::var("QUEUE_VISIBILITY_TIMEOUT_SECS")
.ok()
.and_then(|v| v.parse().ok())
.unwrap_or(300),
),
}
}
pub fn is_sync_mode() -> bool {
env::var("QUEUE_CONNECTION")
.map(|v| v.to_lowercase() == "sync")
.unwrap_or(true) }
pub fn default_queue(mut self, queue: impl Into<String>) -> Self {
self.default_queue = queue.into();
self
}
pub fn max_concurrent_jobs(mut self, count: usize) -> Self {
self.max_concurrent_jobs = count;
self
}
pub fn with_sleep_duration(mut self, d: Duration) -> Self {
self.sleep_duration = d;
self
}
pub fn with_visibility_timeout(mut self, d: Duration) -> Self {
self.visibility_timeout = d;
self
}
}
#[cfg(test)]
mod tests {
use super::*;
use serial_test::serial;
struct EnvGuard {
vars: Vec<String>,
}
impl EnvGuard {
fn new() -> Self {
Self { vars: Vec::new() }
}
fn also_set(&mut self, key: &str, value: &str) {
env::set_var(key, value);
self.vars.push(key.to_string());
}
fn also_remove(&mut self, key: &str) {
env::remove_var(key);
self.vars.push(key.to_string());
}
}
impl Drop for EnvGuard {
fn drop(&mut self) {
for var in &self.vars {
env::remove_var(var);
}
}
}
#[test]
fn test_default_config() {
let config = QueueConfig::default();
assert_eq!(config.default_queue, "default");
assert_eq!(config.max_concurrent_jobs, 10);
assert_eq!(config.sleep_duration, Duration::from_millis(500));
assert_eq!(config.visibility_timeout, Duration::from_secs(300));
}
#[test]
fn test_builder_pattern() {
let config = QueueConfig::default()
.default_queue("high-priority")
.max_concurrent_jobs(5)
.with_visibility_timeout(Duration::from_secs(60));
assert_eq!(config.default_queue, "high-priority");
assert_eq!(config.max_concurrent_jobs, 5);
assert_eq!(config.visibility_timeout, Duration::from_secs(60));
}
#[test]
fn visibility_timeout_default_is_five_minutes() {
let config = QueueConfig::default();
assert_eq!(config.visibility_timeout, Duration::from_secs(300));
}
#[test]
#[serial]
fn test_from_env_defaults() {
let mut guard = EnvGuard::new();
guard.also_remove("QUEUE_DEFAULT");
guard.also_remove("QUEUE_MAX_CONCURRENT");
guard.also_remove("QUEUE_VISIBILITY_TIMEOUT_SECS");
let config = QueueConfig::from_env();
assert_eq!(config.default_queue, "default");
assert_eq!(config.max_concurrent_jobs, 10);
assert_eq!(config.visibility_timeout, Duration::from_secs(300));
}
#[test]
#[serial]
fn test_from_env_visibility_timeout() {
let mut guard = EnvGuard::new();
guard.also_set("QUEUE_VISIBILITY_TIMEOUT_SECS", "120");
let config = QueueConfig::from_env();
assert_eq!(config.visibility_timeout, Duration::from_secs(120));
}
#[test]
#[serial]
fn test_is_sync_mode() {
let mut guard = EnvGuard::new();
guard.also_remove("QUEUE_CONNECTION");
assert!(QueueConfig::is_sync_mode());
env::set_var("QUEUE_CONNECTION", "sync");
assert!(QueueConfig::is_sync_mode());
env::set_var("QUEUE_CONNECTION", "db");
assert!(!QueueConfig::is_sync_mode());
env::set_var("QUEUE_CONNECTION", "SYNC");
assert!(QueueConfig::is_sync_mode()); }
}