harmos_domain/model/services/
policy.rs1use std::time::Duration;
20use serde::{Deserialize, Serialize};
22use crate::model::operations::policy::{Backoff, PolicyError};
24
25#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
34#[serde(deny_unknown_fields)]
35pub struct ServicePolicy {
36 pub stop_timeout: Duration,
37 pub restart: RestartPolicy,
38}
39
40#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
44#[serde(rename_all = "snake_case", deny_unknown_fields)]
45pub enum RestartPolicy {
46 Never,
47 OnFailure { credit: usize, sustained_health: Duration, backoff: Backoff },
48}
49
50impl ServicePolicy {
55 pub fn validate(self) -> Result<(), PolicyError> {
56 if self.stop_timeout.is_zero() {
57 return Err(PolicyError::Deadline {
58 timeout: self.stop_timeout,
59 attempt_timeout: self.stop_timeout,
60 });
61 }
62 self.restart.validate()
63 }
64}
65
66impl RestartPolicy {
67 pub fn validate(self) -> Result<(), PolicyError> {
68 match self {
69 Self::Never => Ok(()),
70 Self::OnFailure { credit, sustained_health, .. } if credit == 0 || sustained_health.is_zero() => {
71 Err(PolicyError::EmptyRestarts)
72 }
73 Self::OnFailure { backoff, .. } => backoff.validate(),
74 }
75 }
76
77 pub const fn credit(self) -> usize {
78 match self {
79 Self::Never => 0,
80 Self::OnFailure { credit, .. } => credit,
81 }
82 }
83}
84
85#[cfg(test)]
92mod tests {
93 use super::*;
94 use crate::Backoff;
95 use crate::Jitter;
96
97 #[test]
98 fn service_credit_and_backoff() {
99 let delay = Duration::from_millis(10);
100 let backoff = Backoff::Exponential {
101 initial: delay,
102 maximum: delay * 4,
103 jitter: Jitter::None,
104 };
105 let restart = RestartPolicy::OnFailure {
106 credit: 2,
107 sustained_health: Duration::from_secs(1),
108 backoff,
109 };
110 assert_eq!(restart.credit(), 2);
111 assert!(ServicePolicy { stop_timeout: delay, restart }.validate().is_ok());
112 assert!(ServicePolicy { stop_timeout: Duration::ZERO, restart }.validate().is_err());
113 assert!(
114 RestartPolicy::OnFailure {
115 credit: 0,
116 sustained_health: delay,
117 backoff
118 }
119 .validate()
120 .is_err()
121 );
122 assert_eq!(backoff.delay(0, 0).unwrap(), delay);
123 assert_eq!(backoff.delay(usize::MAX, 0).unwrap(), delay * 4);
124 }
125}