scylla/policies/load_balancing/mod.rs
1//! Load balancing configurations\
2//! `Session` can use any load balancing policy which implements the `LoadBalancingPolicy` trait\
3//! See [the book](https://rust-driver.docs.scylladb.com/stable/load-balancing/load-balancing.html) for more information
4
5use crate::cluster::{ClusterState, NodeRef};
6use crate::{
7 errors::RequestAttemptError,
8 routing::{Shard, Token},
9};
10use scylla_cql::frame::{response::result::TableSpec, types};
11
12use std::time::Duration;
13
14mod default;
15mod plan;
16pub use default::{DefaultPolicy, DefaultPolicyBuilder, LatencyAwarenessBuilder};
17pub use plan::Plan;
18
19/// Represents info about statement that can be used by load balancing policies.
20#[derive(Default, Clone, Debug)]
21#[non_exhaustive]
22pub struct RoutingInfo<'a> {
23 /// Requested consistency information allows to route requests to the appropriate
24 /// datacenters. E.g. requests with a LOCAL_ONE consistency should be routed to the same
25 /// datacenter.
26 pub consistency: types::Consistency,
27 pub serial_consistency: Option<types::SerialConsistency>,
28
29 /// Information that are the basis of token-aware routing:
30 /// - token, keyspace for vnodes-based routing;
31 /// - token, keyspace, table for tablets-based routing.
32 pub token: Option<Token>,
33 pub table: Option<&'a TableSpec<'a>>,
34
35 /// If, while preparing, we received from the cluster information that the statement is an LWT,
36 /// then we can use this information for routing optimisation. Namely, an optimisation
37 /// can be performed: the request should be routed to the replicas in a predefined order
38 /// (i. e. always try first to contact replica A, then B if it fails, then C, etc.).
39 /// If false, the request should be routed normally.
40 /// Note: this a Scylla-specific optimisation. Therefore, the flag will be always false for Cassandra.
41 pub is_confirmed_lwt: bool,
42}
43
44/// The fallback list of nodes in the request plan.
45///
46/// It is computed on-demand, only if querying the most preferred node fails
47/// (or when speculative execution is triggered).
48pub type FallbackPlan<'a> =
49 Box<dyn Iterator<Item = (NodeRef<'a>, Option<Shard>)> + Send + Sync + 'a>;
50
51/// Policy that decides which nodes and shards to contact for each request.
52///
53/// When a request is prepared to be sent to ScyllaDB/Cassandra, a `LoadBalancingPolicy`
54/// implementation constructs a load balancing plan. That plan is a list of
55/// targets (target is a node + an optional shard) to which
56/// the driver will try to send the request. The first elements of the plan are the targets which are
57/// the best to contact (e.g. they might have the lowest latency).
58///
59/// Most requests are sent on the first try, so the request execution layer rarely needs to know more
60/// than one target from plan. To better optimize that case, `LoadBalancingPolicy` has two methods:
61/// `pick` and `fallback`. `pick` returns the first target to contact for a given request, `fallback`
62/// returns the rest of the load balancing plan.
63///
64/// `fallback` is called not only if a send to `pick`ed node failed (or when executing
65/// speculatively), but also if `pick` returns `None`.
66///
67/// Usually the driver needs only the first node from load balancing plan (most requests are send
68/// successfully, and there is no need to retry).
69///
70/// This trait is used to produce an iterator of nodes to contact for a given request.
71pub trait LoadBalancingPolicy: Send + Sync + std::fmt::Debug {
72 /// Returns the first node to contact for a given request.
73 fn pick<'a>(
74 &'a self,
75 request: &'a RoutingInfo,
76 cluster: &'a ClusterState,
77 ) -> Option<(NodeRef<'a>, Option<Shard>)>;
78
79 /// Returns all contact-appropriate nodes for a given request.
80 fn fallback<'a>(
81 &'a self,
82 request: &'a RoutingInfo,
83 cluster: &'a ClusterState,
84 ) -> FallbackPlan<'a>;
85
86 /// Invoked each time a request succeeds.
87 fn on_request_success(&self, _request: &RoutingInfo, _latency: Duration, _node: NodeRef<'_>) {}
88
89 /// Invoked each time a request fails.
90 fn on_request_failure(
91 &self,
92 _request: &RoutingInfo,
93 _latency: Duration,
94 _node: NodeRef<'_>,
95 _error: &RequestAttemptError,
96 ) {
97 }
98
99 /// Returns the name of load balancing policy.
100 fn name(&self) -> String;
101}