use std::time::Duration;
use serde::Serialize;
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct ServiceSet {
running: bool,
in_flight: usize,
}
impl ServiceSet {
pub fn start(&mut self) {
self.running = true;
}
pub fn stop(&mut self) {
self.running = false;
}
pub fn begin_request(&mut self) {
self.in_flight = self.in_flight.saturating_add(1);
}
pub fn finish_request(&mut self) {
self.in_flight = self.in_flight.saturating_sub(1);
}
pub fn in_flight(&self) -> usize {
self.in_flight
}
pub fn is_running(&self) -> bool {
self.running
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct GracefulShutdown {
drain_timeout: Duration,
}
impl GracefulShutdown {
pub fn new(drain_timeout: Duration) -> Self {
Self { drain_timeout }
}
pub fn drain(&self, services: &mut ServiceSet) -> DrainOutcome {
let started_with = services.in_flight();
let timed_out = self.drain_timeout.is_zero() && started_with > 0;
if !timed_out {
while services.in_flight() > 0 {
services.finish_request();
}
}
DrainOutcome {
started_with,
remaining: services.in_flight(),
timed_out,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
pub struct DrainOutcome {
pub started_with: usize,
pub remaining: usize,
pub timed_out: bool,
}