use thiserror::Error; const DEFAULT_MAX_CONCURRENT_UNARY: usize = 64; const DEFAULT_MAX_CONCURRENT_SESSIONS: usize = 16; const MAX_CONCURRENCY: usize = 65_535; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct RuntimeLimits { pub max_concurrent_unary: usize, pub max_concurrent_sessions: usize, } impl Default for RuntimeLimits { fn default() -> Self { Self { max_concurrent_unary: DEFAULT_MAX_CONCURRENT_UNARY, max_concurrent_sessions: DEFAULT_MAX_CONCURRENT_SESSIONS, } } } impl RuntimeLimits { pub fn try_new( max_concurrent_unary: usize, max_concurrent_sessions: usize, ) -> Result { if !(1..=MAX_CONCURRENCY).contains(&max_concurrent_unary) { return Err(RuntimeLimitsConfigError::OutOfRange { field: "runtime.max_concurrent_unary", }); } if !(1..=MAX_CONCURRENCY).contains(&max_concurrent_sessions) { return Err(RuntimeLimitsConfigError::OutOfRange { field: "runtime.max_concurrent_sessions", }); } Ok(Self { max_concurrent_unary, max_concurrent_sessions, }) } } #[derive(Debug, Error, Eq, PartialEq)] pub enum RuntimeLimitsConfigError { #[error("runtime limit is outside its allowed bounds: {field}")] OutOfRange { field: &'static str }, } #[cfg(test)] mod tests { use super::{RuntimeLimits, RuntimeLimitsConfigError}; #[test] fn defaults_are_positive() { let limits = RuntimeLimits::default(); assert!(limits.max_concurrent_unary > 0); assert!(limits.max_concurrent_sessions > 0); } #[test] fn value_constructor_rejects_zero() { assert_eq!( RuntimeLimits::try_new(0, 1).unwrap_err(), RuntimeLimitsConfigError::OutOfRange { field: "runtime.max_concurrent_unary" } ); } }