Skip to main content

conreg_client/lb/
mod.rs

1//! # Load Balance Component
2//!
3//! ## [`RandomLoadBalance`]
4//! Random: Select one randomly from the list of available services.
5//!
6//! ## [`RoundRobinLoadBalance`]
7//! Round Robin: Select from the service list in sequential order.
8//!
9//! ## [`WeightRandomLoadBalance`]
10//! Weighted Random: Select from the service list according to weights.
11//!
12//! ## [`WeightRoundRobinLoadBalance`]
13//! Weighted Round Robin: Select from the service list according to weights.
14//!
15//! ## About Weights
16//! Weights can be set through service metadata, typically with a suggested weight range of 1-100.
17//!
18//! # Usage
19//! ```rust
20//! // Initialize Discovery
21//! let _ = init().await;
22//!
23//! // Create a load balance client
24//! let mut client = LoadBalanceClient::new();
25//!
26//! // Optional: Set the load balancing strategy for a service
27//! client.set_strategy("your_service_id", LoadBalanceStrategy::Random);
28//!
29//! // Make a request
30//! let response = client
31//!     .get("lb://your_service_id/hello")
32//!     .await
33//!     .unwrap()
34//!     .send()
35//!     .await;
36//!
37//! println!("Response: {:?}", response.unwrap().text().await.unwrap());
38//! ```
39pub mod client;
40mod random;
41mod round;
42mod weight_random;
43mod weight_round;
44
45use crate::{AppDiscovery, Instance};
46pub use client::LoadBalanceClient;
47pub use random::RandomLoadBalance;
48pub use round::RoundRobinLoadBalance;
49pub use weight_random::WeightRandomLoadBalance;
50pub use weight_round::WeightRoundRobinLoadBalance;
51
52pub trait LoadBalance {
53    /// Get the list of service instances
54    fn instances(
55        &self,
56        service_id: &str,
57    ) -> impl Future<Output = Result<Vec<Instance>, LoadBalanceError>> + Send {
58        async {
59            AppDiscovery::get_instances(service_id)
60                .await
61                .map_err(|e| LoadBalanceError::GetInstancesError(e.to_string()))
62        }
63    }
64
65    /// Get a service instance
66    fn get_instance(
67        &self,
68        service_id: &str,
69    ) -> impl Future<Output = Result<Instance, LoadBalanceError>> + Send;
70}
71
72#[derive(Debug)]
73pub enum LoadBalanceError {
74    /// Failed to get the list of service instances
75    GetInstancesError(String),
76    /// No available instance
77    NoAvailableInstance(String),
78}
79
80impl std::fmt::Display for LoadBalanceError {
81    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
82        match self {
83            LoadBalanceError::GetInstancesError(e) => write!(f, "Failed to get instances: {}", e),
84            LoadBalanceError::NoAvailableInstance(s) => {
85                write!(f, "No available instance for service: {}", s)
86            }
87        }
88    }
89}
90
91impl std::error::Error for LoadBalanceError {}