rocketmq_client_rust/nameserver_discovery/
snapshot.rs1use std::net::SocketAddr;
16use std::sync::Arc;
17use std::time::Duration;
18
19use tokio::time::Instant;
20
21use super::NameServerAuthority;
22
23#[derive(Clone, Copy, Debug, Eq, PartialEq)]
25pub enum NameServerDiscoverySourceKind {
26 Dns,
27}
28
29#[derive(Clone, Copy, Debug, Eq, PartialEq)]
31pub enum NameServerDiscoveryFreshness {
32 Fresh,
33 Stale,
34 Unavailable,
35}
36
37#[derive(Clone, Copy, Debug, Eq, PartialEq)]
39pub enum NameServerDiscoveryErrorCategory {
40 Empty,
41 NxDomain,
42 ServFail,
43 Timeout,
44 Other,
45}
46
47#[derive(Clone, Debug, Eq, PartialEq)]
49pub struct NameServerDiscoveryStatus {
50 source_kind: NameServerDiscoverySourceKind,
51 generation: u64,
52 freshness: NameServerDiscoveryFreshness,
53 last_successful_refresh_age: Duration,
54 snapshot_age: Duration,
55 ipv4_endpoint_count: usize,
56 ipv6_endpoint_count: usize,
57 healthy_endpoint_count: usize,
58 probing_endpoint_count: usize,
59 draining_endpoint_count: usize,
60 circuit_open_endpoint_count: usize,
61 next_refresh_delay: Duration,
62 last_error_category: Option<NameServerDiscoveryErrorCategory>,
63}
64
65impl NameServerDiscoveryStatus {
66 #[allow(
67 clippy::too_many_arguments,
68 reason = "the fields form one immutable diagnostic snapshot"
69 )]
70 pub(crate) fn new(
71 generation: u64,
72 freshness: NameServerDiscoveryFreshness,
73 last_successful_refresh_age: Duration,
74 snapshot_age: Duration,
75 ipv4_endpoint_count: usize,
76 ipv6_endpoint_count: usize,
77 next_refresh_delay: Duration,
78 last_error_category: Option<NameServerDiscoveryErrorCategory>,
79 ) -> Self {
80 Self {
81 source_kind: NameServerDiscoverySourceKind::Dns,
82 generation,
83 freshness,
84 last_successful_refresh_age,
85 snapshot_age,
86 ipv4_endpoint_count,
87 ipv6_endpoint_count,
88 healthy_endpoint_count: 0,
89 probing_endpoint_count: 0,
90 draining_endpoint_count: 0,
91 circuit_open_endpoint_count: 0,
92 next_refresh_delay,
93 last_error_category,
94 }
95 }
96
97 #[must_use]
98 pub fn source_kind(&self) -> NameServerDiscoverySourceKind {
99 self.source_kind
100 }
101
102 #[must_use]
103 pub fn generation(&self) -> u64 {
104 self.generation
105 }
106
107 #[must_use]
108 pub fn freshness(&self) -> NameServerDiscoveryFreshness {
109 self.freshness
110 }
111
112 #[must_use]
113 pub fn last_successful_refresh_age(&self) -> Duration {
114 self.last_successful_refresh_age
115 }
116
117 #[must_use]
118 pub fn snapshot_age(&self) -> Duration {
119 self.snapshot_age
120 }
121
122 #[must_use]
123 pub fn ipv4_endpoint_count(&self) -> usize {
124 self.ipv4_endpoint_count
125 }
126
127 #[must_use]
128 pub fn ipv6_endpoint_count(&self) -> usize {
129 self.ipv6_endpoint_count
130 }
131
132 #[must_use]
133 pub fn healthy_endpoint_count(&self) -> usize {
134 self.healthy_endpoint_count
135 }
136
137 #[must_use]
138 pub fn probing_endpoint_count(&self) -> usize {
139 self.probing_endpoint_count
140 }
141
142 #[must_use]
143 pub fn draining_endpoint_count(&self) -> usize {
144 self.draining_endpoint_count
145 }
146
147 #[must_use]
148 pub fn circuit_open_endpoint_count(&self) -> usize {
149 self.circuit_open_endpoint_count
150 }
151
152 pub(crate) fn with_transport_counts(
153 mut self,
154 healthy: usize,
155 probing: usize,
156 draining: usize,
157 circuit_open: usize,
158 ) -> Self {
159 self.healthy_endpoint_count = healthy;
160 self.probing_endpoint_count = probing;
161 self.draining_endpoint_count = draining;
162 self.circuit_open_endpoint_count = circuit_open;
163 self
164 }
165
166 #[must_use]
167 pub fn next_refresh_delay(&self) -> Duration {
168 self.next_refresh_delay
169 }
170
171 #[must_use]
172 pub fn last_error_category(&self) -> Option<NameServerDiscoveryErrorCategory> {
173 self.last_error_category
174 }
175}
176
177#[derive(Clone, Debug, Eq, PartialEq)]
179pub struct ResolvedNameServerEndpoint {
180 authority: NameServerAuthority,
181 socket_addr: SocketAddr,
182}
183
184impl ResolvedNameServerEndpoint {
185 pub(crate) fn new(authority: NameServerAuthority, socket_addr: SocketAddr) -> Self {
186 Self { authority, socket_addr }
187 }
188
189 #[must_use]
191 pub fn authority(&self) -> &NameServerAuthority {
192 &self.authority
193 }
194
195 #[must_use]
197 pub fn socket_addr(&self) -> SocketAddr {
198 self.socket_addr
199 }
200}
201
202#[derive(Clone, Copy, Debug, Eq, PartialEq)]
203pub(crate) enum Freshness {
204 Fresh,
205 Stale,
206 Unavailable,
207}
208
209#[derive(Clone, Debug)]
210pub(crate) struct EndpointSnapshot {
211 pub(crate) generation: u64,
212 pub(crate) resolved_at: Instant,
213 pub(crate) valid_until: Instant,
214 pub(crate) freshness: Freshness,
215 pub(crate) endpoints: Arc<[ResolvedNameServerEndpoint]>,
216}
217
218impl EndpointSnapshot {
219 pub(crate) fn unavailable(now: Instant) -> Self {
220 Self {
221 generation: 0,
222 resolved_at: now,
223 valid_until: now,
224 freshness: Freshness::Unavailable,
225 endpoints: Arc::from([]),
226 }
227 }
228
229 pub(crate) fn same_endpoint_set(&self, other: &[ResolvedNameServerEndpoint]) -> bool {
230 if self.endpoints.len() != other.len() {
231 return false;
232 }
233 let mut current = self
234 .endpoints
235 .iter()
236 .map(ResolvedNameServerEndpoint::socket_addr)
237 .collect::<Vec<_>>();
238 let mut candidate = other
239 .iter()
240 .map(ResolvedNameServerEndpoint::socket_addr)
241 .collect::<Vec<_>>();
242 current.sort_unstable();
243 candidate.sort_unstable();
244 current == candidate
245 }
246}