north_common/registry/
service_instance_state.rs

1use crate::registry::service_status_constants::ServiceStatus;
2use chrono::Local;
3
4/// [ServiceInstanceState] contains state of every service node
5#[derive(Clone)]
6pub struct ServiceInstanceState {
7    /// service status
8    status: ServiceStatus,
9
10    /// total api request count
11    total_requests: i64,
12
13    /// total active request count
14    active_requests_count: i64,
15
16    /// weight of the service
17    weight: i64,
18
19    /// API avg response time is milliseconds
20    response_time_avg: i64,
21
22    /// API max response time is milliseconds
23    response_time_max: i64,
24
25    /// active request count timeout in milliseconds
26    active_requests_count_timeout: i16,
27
28    /// last active requests count change timestamp in milliseconds
29    last_active_requests_count_change_timestamp: i64,
30
31    /// first connection timestamp in milliseconds
32    first_connection_timestamp: i64,
33
34    /// last connection failed timestamp in milliseconds
35    last_connection_failed_timestamp: Option<i64>,
36
37    /// last connection failed message
38    last_connection_failed_message: String,
39
40    /// count of requests failures
41    failure_counts: i64,
42
43    /// fixed weight
44    fixed_weight: bool,
45}
46
47impl Default for ServiceInstanceState {
48    fn default() -> Self {
49        ServiceInstanceState {
50            status: Default::default(),
51            total_requests: 0,
52            active_requests_count: 0,
53            weight: 0,
54            response_time_avg: 0,
55            response_time_max: 0,
56            active_requests_count_timeout: 0,
57            last_active_requests_count_change_timestamp: 0,
58            first_connection_timestamp: 0,
59            last_connection_failed_timestamp: None,
60            last_connection_failed_message: "".to_string(),
61            failure_counts: 0,
62            fixed_weight: false,
63        }
64    }
65}
66
67impl ServiceInstanceState {
68    pub fn new(fixed_weight: Option<bool>) -> Self {
69        ServiceInstanceState {
70            status: Default::default(),
71            total_requests: 0,
72            active_requests_count: 0,
73            weight: 0,
74            response_time_avg: 0,
75            response_time_max: 0,
76            active_requests_count_timeout: 0,
77            last_active_requests_count_change_timestamp: 0,
78            first_connection_timestamp: 0,
79            last_connection_failed_timestamp: None,
80            last_connection_failed_message: "".to_string(),
81            failure_counts: 0,
82            fixed_weight: fixed_weight.unwrap_or(false),
83        }
84    }
85
86    pub fn get_active_requests_count(&mut self, current_time: Option<i64>) -> i64 {
87        let mut _current_time = current_time.unwrap_or_else(|| Local::now().timestamp_millis());
88        let count = self.active_requests_count;
89        if count == 0 {
90            0
91        } else if _current_time - self.last_active_requests_count_change_timestamp
92            > (self.active_requests_count_timeout * 1000) as i64
93            || count < 0
94        {
95            self.active_requests_count = 0;
96            self.active_requests_count
97        } else {
98            count
99        }
100    }
101
102    pub fn is_healthy(&self) -> bool {
103        !matches!(self.status, ServiceStatus::Critical)
104    }
105
106    pub fn increment_failure_counts(&mut self) -> i64 {
107        self.failure_counts += 1;
108        self.failure_counts
109    }
110
111    pub fn increment_request_counts(&mut self) -> i64 {
112        self.total_requests += 1;
113        self.total_requests
114    }
115
116    pub fn increment_active_requests(&mut self) -> i64 {
117        self.last_active_requests_count_change_timestamp = Local::now().timestamp_millis();
118        self.active_requests_count += 1;
119        self.active_requests_count
120    }
121
122    pub fn decrement_active_requests(&mut self) -> i64 {
123        if self.active_requests_count < 1 {
124            return 0;
125        }
126
127        self.last_active_requests_count_change_timestamp = Local::now().timestamp_millis();
128        self.active_requests_count -= 1;
129        self.active_requests_count
130    }
131
132    pub fn set_connection_failed_time(&mut self, message: Option<String>) {
133        self.last_connection_failed_timestamp = Some(Local::now().timestamp_millis());
134        self.last_connection_failed_message = message.unwrap_or_default();
135        self.status = ServiceStatus::Critical;
136    }
137
138    pub fn set_first_connection_time(&mut self) {
139        self.first_connection_timestamp = Local::now().timestamp_millis();
140    }
141
142    pub fn set_response_time(&mut self, time: i64) {
143        if !self.fixed_weight {
144            self.weight = time - self.response_time_avg;
145        }
146        self.response_time_avg =
147            (self.response_time_avg * (self.total_requests - 1) + time) / self.total_requests;
148        self.response_time_max = std::cmp::max(self.response_time_max, time);
149    }
150}