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 {}