sentinel_core/core/isolation/
rule.rs1use crate::{base::SentinelRule, Error};
2use serde::{Deserialize, Serialize};
3use serde_json;
4use std::fmt;
5use std::hash::{Hash, Hasher};
6cfg_k8s! {
7 use schemars::JsonSchema;
8 use kube::CustomResource;
9}
10
11#[cfg_attr(feature = "ds_k8s", derive(JsonSchema))]
12#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize, Hash, Eq)]
13pub enum MetricType {
14 Concurrency,
16}
17
18impl Default for MetricType {
19 fn default() -> MetricType {
20 MetricType::Concurrency
21 }
22}
23
24#[cfg_attr(
26 feature = "ds_k8s",
27 derive(CustomResource, JsonSchema),
28 kube(
29 group = "rust.datasource.sentinel.io",
30 version = "v1alpha1",
31 kind = "IsolationResource",
32 namespaced
33 )
34)]
35#[derive(Debug, Clone, Serialize, Deserialize)]
36#[serde(default)]
37pub struct Rule {
38 pub id: String,
40 pub resource: String,
42 pub metric_type: MetricType,
44 pub threshold: u32,
45}
46
47impl Default for Rule {
48 fn default() -> Self {
49 Rule {
50 #[cfg(target_arch = "wasm32")]
51 id: String::new(),
52 #[cfg(not(target_arch = "wasm32"))]
53 id: uuid::Uuid::new_v4().to_string(),
54 resource: String::default(),
55 metric_type: MetricType::default(),
56 threshold: 0,
57 }
58 }
59}
60
61impl PartialEq for Rule {
62 fn eq(&self, other: &Self) -> bool {
63 self.resource == other.resource
64 && self.metric_type == other.metric_type
65 && self.threshold == other.threshold
66 }
67}
68
69impl Eq for Rule {}
70
71impl Hash for Rule {
72 fn hash<H: Hasher>(&self, state: &mut H) {
73 self.id.hash(state);
74 self.resource.hash(state);
75 }
76}
77
78impl SentinelRule for Rule {
79 fn resource_name(&self) -> String {
80 format!("{:?}", self.metric_type)
81 }
82
83 fn is_valid(&self) -> crate::Result<()> {
84 if self.resource.len() == 0 {
85 return Err(Error::msg("empty resource of isolation rule"));
86 }
87
88 if self.threshold == 0 {
89 return Err(Error::msg("zero threshold"));
90 }
91 Ok(())
92 }
93}
94
95impl fmt::Display for Rule {
96 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97 let fmtted = serde_json::to_string_pretty(self).unwrap();
98 write!(f, "{}", fmtted)
99 }
100}
101
102#[cfg(test)]
103mod test {
104 use super::*;
105
106 #[test]
107 #[should_panic(expected = "zero threshold")]
108 fn invalid_threshold() {
109 let rule = Rule {
110 resource: "invalid_threshold".into(),
111 threshold: 0,
112 ..Default::default()
113 };
114 rule.is_valid().unwrap();
115 }
116
117 #[test]
118 #[should_panic(expected = "empty resource of isolation rule")]
119 fn invalid_cpu_usage() {
120 let rule = Rule {
121 threshold: 1,
122 ..Default::default()
123 };
124 rule.is_valid().unwrap();
125 }
126}