| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| use std::sync::Arc; |
| use thiserror::Error; |
| use tokio::sync::{Semaphore, SemaphorePermit}; |
|
|
| |
| #[derive(Debug, Error)] |
| pub enum SchedulerError { |
| #[error("scheduler is closed")] |
| Closed, |
| #[error("request was cancelled")] |
| Cancelled, |
| } |
|
|
| |
| #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
| pub enum Lane { |
| |
| Control, |
| |
| User, |
| |
| Background, |
| } |
|
|
| |
| pub struct Scheduler { |
| control: Arc<Semaphore>, |
| user: Arc<Semaphore>, |
| background: Arc<Semaphore>, |
| wasm: Arc<Semaphore>, |
| http: Arc<Semaphore>, |
| } |
|
|
| |
| #[derive(Debug, Clone)] |
| pub struct SchedulerConfig { |
| pub max_control: usize, |
| pub max_user: usize, |
| pub max_background: usize, |
| pub max_wasm: usize, |
| pub max_http: usize, |
| } |
|
|
| impl Default for SchedulerConfig { |
| fn default() -> Self { |
| Self { |
| max_control: 1, |
| max_user: 4, |
| max_background: 2, |
| max_wasm: 4, |
| max_http: 8, |
| } |
| } |
| } |
|
|
| impl Scheduler { |
| |
| pub fn new() -> Self { |
| Self::with_config(SchedulerConfig::default()) |
| } |
|
|
| |
| pub fn with_config(config: SchedulerConfig) -> Self { |
| Self { |
| control: Arc::new(Semaphore::new(config.max_control)), |
| user: Arc::new(Semaphore::new(config.max_user)), |
| background: Arc::new(Semaphore::new(config.max_background)), |
| wasm: Arc::new(Semaphore::new(config.max_wasm)), |
| http: Arc::new(Semaphore::new(config.max_http)), |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| pub async fn acquire(&self, lane: Lane) -> Result<SemaphorePermit<'_>, SchedulerError> { |
| let sem = match lane { |
| Lane::Control => &self.control, |
| Lane::User => &self.user, |
| Lane::Background => &self.background, |
| }; |
| sem.acquire() |
| .await |
| .map_err(|_| SchedulerError::Closed) |
| } |
|
|
| |
| pub fn try_acquire(&self, lane: Lane) -> Option<SemaphorePermit<'_>> { |
| let sem = match lane { |
| Lane::Control => &self.control, |
| Lane::User => &self.user, |
| Lane::Background => &self.background, |
| }; |
| sem.try_acquire().ok() |
| } |
|
|
| |
| |
| |
| |
| pub async fn acquire_wasm(&self) -> Result<SemaphorePermit<'_>, SchedulerError> { |
| self.wasm |
| .acquire() |
| .await |
| .map_err(|_| SchedulerError::Closed) |
| } |
|
|
| |
| |
| |
| pub async fn acquire_http(&self) -> Result<SemaphorePermit<'_>, SchedulerError> { |
| self.http |
| .acquire() |
| .await |
| .map_err(|_| SchedulerError::Closed) |
| } |
|
|
| |
| pub fn available_permits(&self, lane: Lane) -> usize { |
| let sem = match lane { |
| Lane::Control => &self.control, |
| Lane::User => &self.user, |
| Lane::Background => &self.background, |
| }; |
| sem.available_permits() |
| } |
|
|
| |
| pub fn available_wasm_permits(&self) -> usize { |
| self.wasm.available_permits() |
| } |
|
|
| |
| pub fn available_http_permits(&self) -> usize { |
| self.http.available_permits() |
| } |
| } |
|
|
| impl Default for Scheduler { |
| fn default() -> Self { |
| Self::new() |
| } |
| } |
|
|