Skip to content

Commit 0f9ff48

Browse files
chore: use Option<usize> for healthy routes count
1 parent a633622 commit 0f9ff48

File tree

5 files changed

+32
-27
lines changed

5 files changed

+32
-27
lines changed

ic-agent/src/agent/route_provider.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,11 @@ pub trait RouteProvider: std::fmt::Debug + Send + Sync {
5555
/// Returns the total number of routes and healthy routes as a tuple.
5656
///
5757
/// - First element is the total number of routes available (both healthy and unhealthy)
58-
/// - Second element is the number of currently healthy routes
58+
/// - Second element is the number of currently healthy routes, or None if health status information is unavailable
5959
///
6060
/// A healthy route is one that is available and ready to receive traffic.
6161
/// The specific criteria for what constitutes a "healthy" route is implementation dependent.
62-
fn routes_stats(&self) -> (usize, usize);
62+
fn routes_stats(&self) -> (usize, Option<usize>);
6363
}
6464

6565
/// A simple implementation of the [`RouteProvider`] which produces an even distribution of the urls from the input ones.
@@ -104,8 +104,8 @@ impl RouteProvider for RoundRobinRouteProvider {
104104
Ok(urls)
105105
}
106106

107-
fn routes_stats(&self) -> (usize, usize) {
108-
(self.routes.len(), self.routes.len())
107+
fn routes_stats(&self) -> (usize, Option<usize>) {
108+
(self.routes.len(), None)
109109
}
110110
}
111111

@@ -146,8 +146,8 @@ impl RouteProvider for Url {
146146
fn n_ordered_routes(&self, _: usize) -> Result<Vec<Url>, AgentError> {
147147
Ok(vec![self.route()?])
148148
}
149-
fn routes_stats(&self) -> (usize, usize) {
150-
(1, 1)
149+
fn routes_stats(&self) -> (usize, Option<usize>) {
150+
(1, None)
151151
}
152152
}
153153

@@ -231,7 +231,7 @@ impl RouteProvider for DynamicRouteProvider {
231231
fn n_ordered_routes(&self, n: usize) -> Result<Vec<Url>, AgentError> {
232232
self.inner.n_ordered_routes(n)
233233
}
234-
fn routes_stats(&self) -> (usize, usize) {
234+
fn routes_stats(&self) -> (usize, Option<usize>) {
235235
self.inner.routes_stats()
236236
}
237237
}
@@ -289,8 +289,8 @@ impl<R: RouteProvider> RouteProvider for UrlUntilReady<R> {
289289
self.url.route()
290290
}
291291
}
292-
fn routes_stats(&self) -> (usize, usize) {
293-
(1, 1)
292+
fn routes_stats(&self) -> (usize, Option<usize>) {
293+
(1, None)
294294
}
295295
}
296296

ic-agent/src/agent/route_provider/dynamic_routing/dynamic_route_provider.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ where
187187
Ok(urls)
188188
}
189189

190-
fn routes_stats(&self) -> (usize, usize) {
190+
fn routes_stats(&self) -> (usize, Option<usize>) {
191191
let snapshot = self.routing_snapshot.load();
192192
snapshot.nodes_stats()
193193
}
@@ -422,7 +422,7 @@ mod tests {
422422
tokio::time::sleep(snapshot_update_duration).await;
423423
let routed_domains = route_n_times(6, Arc::clone(&route_provider));
424424
assert_routed_domains(routed_domains, vec![node_1.domain()], 6);
425-
assert_eq!(route_provider.routes_stats(), (1, 1));
425+
assert_eq!(route_provider.routes_stats(), (1, Some(1)));
426426

427427
// Test 2: multiple route() calls return 3 different domains with equal fairness (repetition).
428428
// Two healthy nodes are added to the topology.
@@ -437,15 +437,15 @@ mod tests {
437437
vec![node_1.domain(), node_2.domain(), node_3.domain()],
438438
2,
439439
);
440-
assert_eq!(route_provider.routes_stats(), (3, 3));
440+
assert_eq!(route_provider.routes_stats(), (3, Some(3)));
441441

442442
// Test 3: multiple route() calls return 2 different domains with equal fairness (repetition).
443443
// One node is set to unhealthy.
444444
checker.overwrite_healthy_nodes(vec![node_1.clone(), node_3.clone()]);
445445
tokio::time::sleep(snapshot_update_duration).await;
446446
let routed_domains = route_n_times(6, Arc::clone(&route_provider));
447447
assert_routed_domains(routed_domains, vec![node_1.domain(), node_3.domain()], 3);
448-
assert_eq!(route_provider.routes_stats(), (3, 2));
448+
assert_eq!(route_provider.routes_stats(), (3, Some(2)));
449449

450450
// Test 4: multiple route() calls return 3 different domains with equal fairness (repetition).
451451
// Unhealthy node is set back to healthy.
@@ -457,7 +457,7 @@ mod tests {
457457
vec![node_1.domain(), node_2.domain(), node_3.domain()],
458458
2,
459459
);
460-
assert_eq!(route_provider.routes_stats(), (3, 3));
460+
assert_eq!(route_provider.routes_stats(), (3, Some(3)));
461461

462462
// Test 5: multiple route() calls return 3 different domains with equal fairness (repetition).
463463
// One healthy node is added, but another one goes unhealthy.
@@ -476,7 +476,7 @@ mod tests {
476476
vec![node_2.domain(), node_3.domain(), node_4.domain()],
477477
2,
478478
);
479-
assert_eq!(route_provider.routes_stats(), (4, 3));
479+
assert_eq!(route_provider.routes_stats(), (4, Some(3)));
480480

481481
// Test 6: multiple route() calls return a single domain=api1.com.
482482
// One node is set to unhealthy and one is removed from the topology.
@@ -485,7 +485,7 @@ mod tests {
485485
tokio::time::sleep(snapshot_update_duration).await;
486486
let routed_domains = route_n_times(3, Arc::clone(&route_provider));
487487
assert_routed_domains(routed_domains, vec![node_2.domain()], 3);
488-
assert_eq!(route_provider.routes_stats(), (3, 1));
488+
assert_eq!(route_provider.routes_stats(), (3, Some(1)));
489489
}
490490

491491
#[tokio::test]

ic-agent/src/agent/route_provider/dynamic_routing/snapshot/latency_based_routing.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -323,8 +323,8 @@ impl RoutingSnapshot for LatencyRoutingSnapshot {
323323
true
324324
}
325325

326-
fn nodes_stats(&self) -> (usize, usize) {
327-
(self.existing_nodes.len(), self.healthy_nodes.len())
326+
fn nodes_stats(&self) -> (usize, Option<usize>) {
327+
(self.existing_nodes.len(), Some(self.healthy_nodes.len()))
328328
}
329329
}
330330

@@ -356,7 +356,7 @@ mod tests {
356356
assert!(!snapshot.has_nodes());
357357
assert!(snapshot.next_node().is_none());
358358
assert!(snapshot.next_n_nodes(1).is_empty());
359-
assert_eq!(snapshot.nodes_stats(), (0, 0));
359+
assert_eq!(snapshot.nodes_stats(), (0, Some(0)));
360360
}
361361

362362
#[test]
@@ -372,7 +372,7 @@ mod tests {
372372
assert!(snapshot.nodes_with_metrics.is_empty());
373373
assert!(!snapshot.has_nodes());
374374
assert!(snapshot.next_node().is_none());
375-
assert_eq!(snapshot.nodes_stats(), (0, 0));
375+
assert_eq!(snapshot.nodes_stats(), (0, Some(0)));
376376
}
377377

378378
#[test]
@@ -384,15 +384,15 @@ mod tests {
384384
let node = Node::new("api1.com").unwrap();
385385
let health = HealthCheckStatus::new(Some(Duration::from_secs(1)));
386386
snapshot.existing_nodes.insert(node.clone());
387-
assert_eq!(snapshot.nodes_stats(), (1, 0));
387+
assert_eq!(snapshot.nodes_stats(), (1, Some(0)));
388388
// Check first update
389389
let is_updated = snapshot.update_node(&node, health);
390390
assert!(is_updated);
391391
assert!(snapshot.has_nodes());
392392
let node_with_metrics = snapshot.nodes_with_metrics.first().unwrap();
393393
assert_eq!(node_with_metrics.score, (2.0 / 1.0) / 2.0);
394394
assert_eq!(snapshot.next_node().unwrap(), node);
395-
assert_eq!(snapshot.nodes_stats(), (1, 1));
395+
assert_eq!(snapshot.nodes_stats(), (1, Some(1)));
396396
// Check second update
397397
let health = HealthCheckStatus::new(Some(Duration::from_secs(2)));
398398
let is_updated = snapshot.update_node(&node, health);
@@ -415,7 +415,7 @@ mod tests {
415415
assert_eq!(snapshot.nodes_with_metrics.len(), 1);
416416
assert_eq!(snapshot.existing_nodes.len(), 1);
417417
assert!(snapshot.next_node().is_none());
418-
assert_eq!(snapshot.nodes_stats(), (1, 0));
418+
assert_eq!(snapshot.nodes_stats(), (1, Some(0)));
419419
}
420420

421421
#[test]

ic-agent/src/agent/route_provider/dynamic_routing/snapshot/round_robin_routing.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ impl RoutingSnapshot for RoundRobinRoutingSnapshot {
107107
}
108108
}
109109

110-
fn nodes_stats(&self) -> (usize, usize) {
111-
(self.existing_nodes.len(), self.healthy_nodes.len())
110+
fn nodes_stats(&self) -> (usize, Option<usize>) {
111+
(self.existing_nodes.len(), Some(self.healthy_nodes.len()))
112112
}
113113
}
114114

ic-agent/src/agent/route_provider/dynamic_routing/snapshot/routing_snapshot.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ pub trait RoutingSnapshot: Send + Sync + Clone + Debug {
1515
fn sync_nodes(&mut self, nodes: &[Node]) -> bool;
1616
/// Updates the health status of a specific node, returning `true` if the node was found and updated.
1717
fn update_node(&mut self, node: &Node, health: HealthCheckStatus) -> bool;
18-
/// Returns the total number of nodes and healthy nodes as a tuple with first and second element, respectively.
19-
fn nodes_stats(&self) -> (usize, usize);
18+
/// Returns the total number of nodes and healthy nodes as a tuple.
19+
///
20+
/// - First element is the total number of nodes available (both healthy and unhealthy)
21+
/// - Second element is the number of currently healthy nodes, or None if health status information is unavailable
22+
///
23+
/// The specific criteria for what constitutes a "healthy" node is implementation dependent.
24+
fn nodes_stats(&self) -> (usize, Option<usize>);
2025
}

0 commit comments

Comments
 (0)