use std::time::Duration;
use serde::{Deserialize, Serialize};
use super::{
DEFAULT_EVENT_QUEUE_CAPACITY, DEFAULT_REQUEST_MAX_CONCURRENCY, DEFAULT_REQUEST_QUEUE_CAPACITY,
PlanResolutionError,
};
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum CapabilityCardinality {
One,
Optional,
Many,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum CapabilityOperationKind {
Request,
Stream,
Event,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct RequestAdmissionPlan {
queue_capacity: usize,
max_concurrency: usize,
}
impl RequestAdmissionPlan {
pub const fn new(queue_capacity: usize, max_concurrency: usize) -> Self {
Self {
queue_capacity,
max_concurrency,
}
}
pub const fn queue_capacity(self) -> usize {
self.queue_capacity
}
pub const fn max_concurrency(self) -> usize {
self.max_concurrency
}
pub(super) fn validate(
self,
capability_id: &str,
operation: &str,
) -> Result<(), PlanResolutionError> {
if self.max_concurrency == 0 {
return Err(PlanResolutionError::InvalidRequestAdmission {
capability_id: capability_id.to_owned(),
operation: operation.to_owned(),
queue_capacity: self.queue_capacity,
max_concurrency: self.max_concurrency,
});
}
Ok(())
}
}
impl Default for RequestAdmissionPlan {
fn default() -> Self {
Self::new(
DEFAULT_REQUEST_QUEUE_CAPACITY,
DEFAULT_REQUEST_MAX_CONCURRENCY,
)
}
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct EventAdmissionPlan {
capacity: usize,
}
impl EventAdmissionPlan {
pub const fn new(capacity: usize) -> Self {
Self { capacity }
}
pub const fn capacity(self) -> usize {
self.capacity
}
}
impl Default for EventAdmissionPlan {
fn default() -> Self {
Self::new(DEFAULT_EVENT_QUEUE_CAPACITY)
}
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum RestartMode {
Never,
OnFailure,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct RestartPolicy {
mode: RestartMode,
max_attempts: usize,
window: Duration,
backoff: Duration,
jitter: Duration,
stability: Duration,
}
impl RestartPolicy {
pub const fn never() -> Self {
Self {
mode: RestartMode::Never,
max_attempts: 0,
window: Duration::ZERO,
backoff: Duration::ZERO,
jitter: Duration::ZERO,
stability: Duration::ZERO,
}
}
pub const fn on_failure(
max_attempts: usize,
window: Duration,
backoff: Duration,
jitter: Duration,
stability: Duration,
) -> Self {
Self {
mode: RestartMode::OnFailure,
max_attempts,
window,
backoff,
jitter,
stability,
}
}
pub const fn mode(self) -> RestartMode {
self.mode
}
pub const fn max_attempts(self) -> usize {
self.max_attempts
}
pub const fn window(self) -> Duration {
self.window
}
pub const fn backoff(self) -> Duration {
self.backoff
}
pub const fn jitter(self) -> Duration {
self.jitter
}
pub const fn stability(self) -> Duration {
self.stability
}
pub(super) fn validate(&self, instance_key: &str) -> Result<(), PlanResolutionError> {
if self.mode == RestartMode::OnFailure && (self.max_attempts == 0 || self.window.is_zero())
{
return Err(PlanResolutionError::InvalidRestartPolicy {
instance_key: instance_key.to_owned(),
max_attempts: self.max_attempts,
window: self.window,
});
}
Ok(())
}
}
impl Default for RestartPolicy {
fn default() -> Self {
Self::never()
}
}
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum ModuleCriticality {
#[default]
NonCritical,
Critical,
}
impl ModuleCriticality {
pub const fn is_critical(self) -> bool {
matches!(self, Self::Critical)
}
}