use core::time::Duration;
use crate::utils::BasisPoints;
const DEFAULT_SCALE_UP_COOLDOWN: Duration = Duration::from_secs(30);
const DEFAULT_SCALE_DOWN_COOLDOWN: Duration = Duration::from_secs(60);
#[derive(Debug, Clone, Copy)]
pub struct ServletScaleConf {
pub min_instances: usize,
pub max_instances: usize,
pub scale_up_threshold: BasisPoints,
pub scale_down_threshold: BasisPoints,
pub scale_up_cooldown: Duration,
pub scale_down_cooldown: Duration,
}
impl Default for ServletScaleConf {
fn default() -> Self {
Self {
min_instances: 1,
max_instances: 10,
scale_up_threshold: BasisPoints::new(8000),
scale_down_threshold: BasisPoints::new(2000),
scale_up_cooldown: DEFAULT_SCALE_UP_COOLDOWN,
scale_down_cooldown: DEFAULT_SCALE_DOWN_COOLDOWN,
}
}
}
#[derive(Debug, Clone)]
pub struct ScalingMetrics {
pub servlet_type: Vec<u8>,
pub utilization: BasisPoints,
pub current_instances: usize,
pub config: ServletScaleConf,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ScalingDecision {
Hold,
ScaleUp,
ScaleDown,
}
impl ScalingDecision {
#[must_use]
pub fn evaluate(metrics: &ScalingMetrics) -> Self {
let utilization = metrics.utilization.get();
let up_threshold = metrics.config.scale_up_threshold.get();
let down_threshold = metrics.config.scale_down_threshold.get();
if utilization > up_threshold && metrics.current_instances < metrics.config.max_instances {
ScalingDecision::ScaleUp
} else if utilization < down_threshold && metrics.current_instances > metrics.config.min_instances {
ScalingDecision::ScaleDown
} else {
ScalingDecision::Hold
}
}
}