use tokio::sync::{Semaphore, SemaphorePermit};
use crate::web::Error;
pub struct Bulkhead {
sem: Semaphore,
name: &'static str,
}
impl Bulkhead {
pub const fn new(name: &'static str, max_concurrent: usize) -> Self {
Self {
sem: Semaphore::const_new(max_concurrent),
name,
}
}
pub fn try_enter(&self) -> Result<SemaphorePermit<'_>, Error> {
let result = self.sem.try_acquire().map_err(|_| {
metrics::counter!("bulkhead_rejected_total", "name" => self.name).increment(1);
Error::ServiceUnavailable("bulkhead saturated")
});
metrics::gauge!("bulkhead_available", "name" => self.name)
.set(self.sem.available_permits() as f64);
result
}
pub fn available(&self) -> usize {
self.sem.available_permits()
}
}