pingora_load_balancing/
discovery.rs1use arc_swap::ArcSwap;
18use async_trait::async_trait;
19use http::Extensions;
20use pingora_core::protocols::l4::socket::SocketAddr;
21use pingora_error::Result;
22use std::io::Result as IoResult;
23use std::net::ToSocketAddrs;
24use std::{
25 collections::{BTreeSet, HashMap},
26 sync::Arc,
27};
28
29use crate::Backend;
30
31#[async_trait]
33pub trait ServiceDiscovery {
34 async fn discover(&self) -> Result<(BTreeSet<Backend>, HashMap<u64, bool>)>;
38}
39
40#[derive(Default)]
44pub struct Static {
45 backends: ArcSwap<BTreeSet<Backend>>,
46}
47
48impl Static {
49 pub fn new(backends: BTreeSet<Backend>) -> Box<Self> {
51 Box::new(Static {
52 backends: ArcSwap::new(Arc::new(backends)),
53 })
54 }
55
56 pub fn try_from_iter<A, T: IntoIterator<Item = A>>(iter: T) -> IoResult<Box<Self>>
58 where
59 A: ToSocketAddrs,
60 {
61 let mut upstreams = BTreeSet::new();
62 for addrs in iter.into_iter() {
63 let addrs = addrs.to_socket_addrs()?.map(|addr| Backend {
64 addr: SocketAddr::Inet(addr),
65 weight: 1,
66 ext: Extensions::new(),
67 });
68 upstreams.extend(addrs);
69 }
70 Ok(Self::new(upstreams))
71 }
72
73 pub fn get(&self) -> BTreeSet<Backend> {
75 BTreeSet::clone(&self.backends.load())
76 }
77
78 #[allow(dead_code)]
83 pub(crate) fn set(&self, backends: BTreeSet<Backend>) {
84 self.backends.store(backends.into())
85 }
86
87 #[allow(dead_code)]
88 pub(crate) fn add(&self, backend: Backend) {
89 let mut new = self.get();
90 new.insert(backend);
91 self.set(new)
92 }
93
94 #[allow(dead_code)]
95 pub(crate) fn remove(&self, backend: &Backend) {
96 let mut new = self.get();
97 new.remove(backend);
98 self.set(new)
99 }
100}
101
102#[async_trait]
103impl ServiceDiscovery for Static {
104 async fn discover(&self) -> Result<(BTreeSet<Backend>, HashMap<u64, bool>)> {
105 let health = HashMap::new();
107 Ok((self.get(), health))
108 }
109}