use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct DutyDispatchStatus {
pub max_concurrent: u32,
pub in_flight: u32,
pub available_slots: usize,
pub queue_size: usize,
}
impl DutyDispatchStatus {
pub fn new(
max_concurrent: u32,
in_flight: u32,
available_slots: usize,
queue_size: usize,
) -> Self {
Self {
max_concurrent,
in_flight,
available_slots,
queue_size,
}
}
pub fn has_capacity(&self) -> bool {
self.available_slots > 0
}
pub fn utilization(&self) -> f64 {
if self.max_concurrent == 0 {
return 0.0;
}
self.in_flight as f64 / self.max_concurrent as f64
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SetMaxConcurrentRequest {
#[serde(default)]
pub version: u16,
pub max_concurrent: u32,
}
impl SetMaxConcurrentRequest {
pub fn new(max_concurrent: u32) -> Self {
Self {
version: 0,
max_concurrent,
}
}
pub fn validate(&self) -> Result<(), &'static str> {
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_duty_dispatch_status_serialization() {
let status = DutyDispatchStatus::new(50, 23, 27, 15);
let json = serde_json::to_string(&status).unwrap();
let deserialized: DutyDispatchStatus = serde_json::from_str(&json).unwrap();
assert_eq!(status, deserialized);
}
#[test]
fn test_duty_dispatch_status_has_capacity() {
let status_with_capacity = DutyDispatchStatus::new(50, 23, 27, 10);
assert!(status_with_capacity.has_capacity());
let status_full = DutyDispatchStatus::new(50, 50, 0, 10);
assert!(!status_full.has_capacity());
}
#[test]
fn test_duty_dispatch_status_utilization() {
let status = DutyDispatchStatus::new(100, 50, 50, 10);
assert!((status.utilization() - 0.5).abs() < f64::EPSILON);
let status_empty = DutyDispatchStatus::new(100, 0, 100, 10);
assert!((status_empty.utilization() - 0.0).abs() < f64::EPSILON);
let status_full = DutyDispatchStatus::new(100, 100, 0, 10);
assert!((status_full.utilization() - 1.0).abs() < f64::EPSILON);
let status_zero = DutyDispatchStatus::new(0, 0, 0, 0);
assert!((status_zero.utilization() - 0.0).abs() < f64::EPSILON);
}
#[test]
fn test_set_max_concurrent_request_serialization() {
let request = SetMaxConcurrentRequest::new(100);
let json = serde_json::to_string(&request).unwrap();
assert_eq!(json, r#"{"version":0,"max_concurrent":100}"#);
let deserialized: SetMaxConcurrentRequest = serde_json::from_str(&json).unwrap();
assert_eq!(request, deserialized);
}
#[test]
fn test_set_max_concurrent_request_validation() {
let valid_request = SetMaxConcurrentRequest::new(50);
assert!(valid_request.validate().is_ok());
let zero_request = SetMaxConcurrentRequest::new(0);
assert!(zero_request.validate().is_ok());
let high_request = SetMaxConcurrentRequest::new(10000);
assert!(high_request.validate().is_ok());
}
}