use std::sync::{Arc, RwLock};
use super::{AccessControl, RateLimitConfig};
#[derive(Debug)]
pub struct ServerConfig {
pub access_control: AccessControl,
pub rate_limit: Option<RateLimitConfig>,
pub enable_interleaved: bool,
}
#[derive(Clone, Debug)]
pub struct ConfigHandle {
inner: Arc<RwLock<ServerConfig>>,
}
impl ConfigHandle {
pub(crate) fn new(inner: Arc<RwLock<ServerConfig>>) -> Self {
Self { inner }
}
pub fn update(&self, f: impl FnOnce(&mut ServerConfig)) {
let mut config = self.inner.write().expect("config lock poisoned");
f(&mut config);
}
pub fn snapshot(&self) -> ConfigSnapshot {
let config = self.inner.read().expect("config lock poisoned");
ConfigSnapshot {
rate_limit: config.rate_limit.clone(),
enable_interleaved: config.enable_interleaved,
}
}
}
#[derive(Clone, Debug)]
pub struct ConfigSnapshot {
pub rate_limit: Option<RateLimitConfig>,
pub enable_interleaved: bool,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_config_handle_update() {
let config = Arc::new(RwLock::new(ServerConfig {
access_control: AccessControl::default(),
rate_limit: None,
enable_interleaved: false,
}));
let handle = ConfigHandle::new(config.clone());
handle.update(|c| {
c.enable_interleaved = true;
});
let snap = handle.snapshot();
assert!(snap.enable_interleaved);
}
#[test]
fn test_config_handle_clone_shares_state() {
let config = Arc::new(RwLock::new(ServerConfig {
access_control: AccessControl::default(),
rate_limit: None,
enable_interleaved: false,
}));
let handle1 = ConfigHandle::new(config);
let handle2 = handle1.clone();
handle1.update(|c| {
c.enable_interleaved = true;
});
let snap = handle2.snapshot();
assert!(snap.enable_interleaved);
}
#[test]
fn test_config_snapshot_rate_limit() {
let config = Arc::new(RwLock::new(ServerConfig {
access_control: AccessControl::default(),
rate_limit: Some(RateLimitConfig::default()),
enable_interleaved: false,
}));
let handle = ConfigHandle::new(config);
let snap = handle.snapshot();
assert!(snap.rate_limit.is_some());
}
}