1use std::time::Duration;
2
3use serde::{Deserialize, Serialize};
4
5use super::{
6 DEFAULT_EVENT_QUEUE_CAPACITY, DEFAULT_REQUEST_MAX_CONCURRENCY, DEFAULT_REQUEST_QUEUE_CAPACITY,
7 PlanResolutionError,
8};
9
10#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
12#[serde(rename_all = "snake_case")]
13pub enum CapabilityCardinality {
14 One,
16 Optional,
18 Many,
20}
21
22#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
24#[serde(rename_all = "snake_case")]
25pub enum CapabilityOperationKind {
26 Request,
28 Stream,
30 Event,
32}
33
34#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
40pub struct RequestAdmissionPlan {
41 queue_capacity: usize,
42 max_concurrency: usize,
43}
44
45impl RequestAdmissionPlan {
46 pub const fn new(queue_capacity: usize, max_concurrency: usize) -> Self {
48 Self {
49 queue_capacity,
50 max_concurrency,
51 }
52 }
53
54 pub const fn queue_capacity(self) -> usize {
56 self.queue_capacity
57 }
58
59 pub const fn max_concurrency(self) -> usize {
61 self.max_concurrency
62 }
63
64 pub(super) fn validate(
65 self,
66 capability_id: &str,
67 operation: &str,
68 ) -> Result<(), PlanResolutionError> {
69 if self.max_concurrency == 0 {
70 return Err(PlanResolutionError::InvalidRequestAdmission {
71 capability_id: capability_id.to_owned(),
72 operation: operation.to_owned(),
73 queue_capacity: self.queue_capacity,
74 max_concurrency: self.max_concurrency,
75 });
76 }
77 Ok(())
78 }
79}
80
81impl Default for RequestAdmissionPlan {
82 fn default() -> Self {
83 Self::new(
84 DEFAULT_REQUEST_QUEUE_CAPACITY,
85 DEFAULT_REQUEST_MAX_CONCURRENCY,
86 )
87 }
88}
89
90#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
95pub struct EventAdmissionPlan {
96 capacity: usize,
97}
98
99impl EventAdmissionPlan {
100 pub const fn new(capacity: usize) -> Self {
102 Self { capacity }
103 }
104
105 pub const fn capacity(self) -> usize {
107 self.capacity
108 }
109}
110
111impl Default for EventAdmissionPlan {
112 fn default() -> Self {
113 Self::new(DEFAULT_EVENT_QUEUE_CAPACITY)
114 }
115}
116
117#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
119#[serde(rename_all = "snake_case")]
120pub enum RestartMode {
121 Never,
123 OnFailure,
125}
126
127#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
129pub struct RestartPolicy {
130 mode: RestartMode,
131 max_attempts: usize,
132 window: Duration,
133 backoff: Duration,
134 jitter: Duration,
135 stability: Duration,
136}
137
138impl RestartPolicy {
139 pub const fn never() -> Self {
141 Self {
142 mode: RestartMode::Never,
143 max_attempts: 0,
144 window: Duration::ZERO,
145 backoff: Duration::ZERO,
146 jitter: Duration::ZERO,
147 stability: Duration::ZERO,
148 }
149 }
150
151 pub const fn on_failure(
153 max_attempts: usize,
154 window: Duration,
155 backoff: Duration,
156 jitter: Duration,
157 stability: Duration,
158 ) -> Self {
159 Self {
160 mode: RestartMode::OnFailure,
161 max_attempts,
162 window,
163 backoff,
164 jitter,
165 stability,
166 }
167 }
168
169 pub const fn mode(self) -> RestartMode {
171 self.mode
172 }
173
174 pub const fn max_attempts(self) -> usize {
176 self.max_attempts
177 }
178
179 pub const fn window(self) -> Duration {
181 self.window
182 }
183
184 pub const fn backoff(self) -> Duration {
186 self.backoff
187 }
188
189 pub const fn jitter(self) -> Duration {
191 self.jitter
192 }
193
194 pub const fn stability(self) -> Duration {
196 self.stability
197 }
198
199 pub(super) fn validate(&self, instance_key: &str) -> Result<(), PlanResolutionError> {
200 if self.mode == RestartMode::OnFailure && (self.max_attempts == 0 || self.window.is_zero())
201 {
202 return Err(PlanResolutionError::InvalidRestartPolicy {
203 instance_key: instance_key.to_owned(),
204 max_attempts: self.max_attempts,
205 window: self.window,
206 });
207 }
208 Ok(())
209 }
210}
211
212impl Default for RestartPolicy {
213 fn default() -> Self {
214 Self::never()
215 }
216}
217
218#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
220#[serde(rename_all = "snake_case")]
221pub enum ModuleCriticality {
222 #[default]
224 NonCritical,
225 Critical,
227}
228
229impl ModuleCriticality {
230 pub const fn is_critical(self) -> bool {
232 matches!(self, Self::Critical)
233 }
234}