satex_load_balancer/
load_balancer.rs1use crate::health_check::HealthCheck;
2use crate::selector::{BackendIter, BoxSelector, Selector};
3use crate::{Backend, Backends};
4use satex_core::Error;
5use std::time::Duration;
6
7pub struct LoadBalancer {
9 selector: BoxSelector,
10 pub(crate) backends: Backends,
11 pub(crate) update_frequency: Option<Duration>,
12 pub(crate) health_check_frequency: Option<Duration>,
13 pub(crate) health_check_parallel: bool,
14}
15
16impl LoadBalancer {
17 pub fn new<S>(backends: Backends, selector: S) -> Self
19 where
20 S: Selector + Send + Sync + 'static,
21 S::Iter: Send + Sync + 'static,
22 {
23 let selector = BoxSelector::new(selector);
24 Self {
25 backends,
26 selector,
27 update_frequency: None,
28 health_check_frequency: None,
29 health_check_parallel: false,
30 }
31 }
32
33 pub fn with_health_check(
35 mut self,
36 health_check: impl HealthCheck + Send + Sync + 'static,
37 ) -> Self {
38 self.backends = self.backends.with_health_check(health_check);
39 self
40 }
41
42 pub fn with_update_frequency(mut self, update_frequency: Duration) -> Self {
44 self.update_frequency = Some(update_frequency);
45 self
46 }
47
48 pub fn with_health_check_frequency(mut self, health_check_frequency: Duration) -> Self {
50 self.health_check_frequency = Some(health_check_frequency);
51 self
52 }
53
54 pub fn with_health_check_parallel(mut self, health_check_parallel: bool) -> Self {
55 self.health_check_parallel = health_check_parallel;
56 self
57 }
58
59 pub async fn update(&self) -> Result<(), Error> {
63 self.backends
64 .update(|backends| self.selector.update(&backends))
65 .await
66 }
67
68 pub fn select(&self, key: &[u8]) -> Option<Backend> {
75 self.select_with(key, |_, health| health)
76 }
77
78 pub fn select_with<F>(&self, key: &[u8], accept: F) -> Option<Backend>
84 where
85 F: Fn(&Backend, bool) -> bool,
86 {
87 let mut iter = self.selector.iter(key);
88 while let Some(b) = iter.next() {
89 if accept(b, self.backends.ready(b)) {
90 return Some(b.clone());
91 }
92 }
93 None
94 }
95}