1use std::{net::SocketAddr, time::Duration};
2
3#[derive(Debug, Clone, PartialEq, Eq)]
5pub struct RpcClientConfig {
6 pub endpoint: String,
8 pub connect_timeout: Duration,
10 pub request_timeout: Duration,
12 pub resilience: RpcResilienceConfig,
14 pub retry: RpcRetryConfig,
16 pub deadline: RpcDeadlineConfig,
18 pub load_balance: RpcLoadBalanceConfig,
20 pub discovery: RpcDiscoveryConfig,
22 pub streaming: RpcStreamingConfig,
24}
25
26impl RpcClientConfig {
27 pub fn new(endpoint: impl Into<String>) -> Self {
29 Self {
30 endpoint: endpoint.into(),
31 connect_timeout: Duration::from_secs(3),
32 request_timeout: Duration::from_secs(5),
33 resilience: RpcResilienceConfig::default(),
34 retry: RpcRetryConfig::default(),
35 deadline: RpcDeadlineConfig::default(),
36 load_balance: RpcLoadBalanceConfig::default(),
37 discovery: RpcDiscoveryConfig::default(),
38 streaming: RpcStreamingConfig::default(),
39 }
40 }
41}
42
43impl RpcClientConfig {
44 pub fn go_zero_defaults(endpoint: impl Into<String>) -> Self {
46 Self {
47 resilience: RpcResilienceConfig::go_zero_defaults(),
48 retry: RpcRetryConfig::go_zero_defaults(),
49 deadline: RpcDeadlineConfig::go_zero_defaults(),
50 load_balance: RpcLoadBalanceConfig::go_zero_defaults(),
51 streaming: RpcStreamingConfig::go_zero_defaults(),
52 ..Self::new(endpoint)
53 }
54 }
55}
56
57#[derive(Debug, Clone, PartialEq, Eq)]
59pub struct RpcServerConfig {
60 pub name: String,
62 pub addr: SocketAddr,
64 pub resilience: RpcResilienceConfig,
66 pub streaming: RpcStreamingConfig,
68}
69
70impl RpcServerConfig {
71 pub fn new(name: impl Into<String>, addr: SocketAddr) -> Self {
73 Self {
74 name: name.into(),
75 addr,
76 resilience: RpcResilienceConfig::default(),
77 streaming: RpcStreamingConfig::default(),
78 }
79 }
80}
81
82impl RpcServerConfig {
83 pub fn go_zero_defaults(name: impl Into<String>, addr: SocketAddr) -> Self {
85 Self {
86 resilience: RpcResilienceConfig::go_zero_defaults(),
87 streaming: RpcStreamingConfig::go_zero_defaults(),
88 ..Self::new(name, addr)
89 }
90 }
91}
92
93#[derive(Debug, Clone, PartialEq, Eq)]
95pub struct RpcRetryConfig {
96 pub enabled: bool,
98 pub max_attempts: u32,
100 pub initial_backoff: Duration,
102 pub max_backoff: Duration,
104 pub retryable_codes: Vec<tonic::Code>,
106}
107
108impl Default for RpcRetryConfig {
109 fn default() -> Self {
110 Self {
111 enabled: false,
112 max_attempts: 1,
113 initial_backoff: Duration::from_millis(50),
114 max_backoff: Duration::from_secs(1),
115 retryable_codes: vec![
116 tonic::Code::Unavailable,
117 tonic::Code::DeadlineExceeded,
118 tonic::Code::ResourceExhausted,
119 ],
120 }
121 }
122}
123
124impl RpcRetryConfig {
125 pub fn go_zero_defaults() -> Self {
127 Self {
128 enabled: true,
129 max_attempts: 3,
130 initial_backoff: Duration::from_millis(50),
131 max_backoff: Duration::from_millis(500),
132 ..Self::default()
133 }
134 }
135}
136
137#[derive(Debug, Clone, PartialEq, Eq)]
139pub struct RpcDeadlineConfig {
140 pub propagate: bool,
142 pub clip_retries_to_budget: bool,
144}
145
146impl Default for RpcDeadlineConfig {
147 fn default() -> Self {
148 Self {
149 propagate: false,
150 clip_retries_to_budget: true,
151 }
152 }
153}
154
155impl RpcDeadlineConfig {
156 pub fn go_zero_defaults() -> Self {
158 Self {
159 propagate: true,
160 clip_retries_to_budget: true,
161 }
162 }
163}
164
165#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
167pub enum LoadBalancePolicy {
168 #[default]
170 Static,
171 WeightedRoundRobin,
173}
174
175#[derive(Debug, Clone, PartialEq, Eq, Default)]
177pub struct RpcLoadBalanceConfig {
178 pub policy: LoadBalancePolicy,
180}
181
182impl RpcLoadBalanceConfig {
183 pub fn go_zero_defaults() -> Self {
185 Self {
186 policy: LoadBalancePolicy::WeightedRoundRobin,
187 }
188 }
189}
190
191#[derive(Debug, Clone, PartialEq, Eq, Default)]
193pub struct RpcDiscoveryConfig {
194 pub service: Option<String>,
196}
197
198#[derive(Debug, Clone, PartialEq, Eq, Default)]
200pub struct RpcStreamingConfig {
201 pub observe: bool,
203 pub resilience: bool,
205 pub timeout: Option<Duration>,
207}
208
209impl RpcStreamingConfig {
210 pub fn go_zero_defaults() -> Self {
212 Self {
213 observe: true,
214 resilience: true,
215 timeout: Some(Duration::from_secs(30)),
216 }
217 }
218}
219
220#[derive(Debug, Clone, PartialEq, Eq)]
222pub struct RpcResilienceConfig {
223 pub breaker_enabled: bool,
225 pub breaker_failure_threshold: u32,
227 pub breaker_reset_timeout: Duration,
229 pub breaker_sre_enabled: bool,
231 pub breaker_sre_k_millis: u32,
233 pub breaker_sre_protection: u64,
235 pub max_concurrency: Option<usize>,
237 pub request_timeout: Duration,
239 pub shedding_enabled: bool,
241 pub shedding_max_in_flight: Option<usize>,
243 pub shedding_min_request_count: u64,
245 pub shedding_max_latency: Duration,
247 pub shedding_cpu_threshold_millis: u32,
249 pub shedding_cool_off: Duration,
251 pub shedding_window_buckets: usize,
253 pub shedding_window_bucket_duration: Duration,
255 #[cfg(all(feature = "resil", feature = "cache-redis"))]
257 pub rate_limiter: RpcRateLimiterConfig,
258}
259
260impl Default for RpcResilienceConfig {
261 fn default() -> Self {
262 Self {
263 breaker_enabled: false,
264 breaker_failure_threshold: 5,
265 breaker_reset_timeout: Duration::from_secs(30),
266 breaker_sre_enabled: false,
267 breaker_sre_k_millis: 1500,
268 breaker_sre_protection: 5,
269 max_concurrency: None,
270 request_timeout: Duration::from_secs(5),
271 shedding_enabled: false,
272 shedding_max_in_flight: None,
273 shedding_min_request_count: 20,
274 shedding_max_latency: Duration::from_millis(250),
275 shedding_cpu_threshold_millis: 900,
276 shedding_cool_off: Duration::from_secs(1),
277 shedding_window_buckets: 50,
278 shedding_window_bucket_duration: Duration::from_millis(100),
279 #[cfg(all(feature = "resil", feature = "cache-redis"))]
280 rate_limiter: RpcRateLimiterConfig::default(),
281 }
282 }
283}
284
285impl RpcResilienceConfig {
286 pub fn go_zero_defaults() -> Self {
288 Self {
289 breaker_enabled: true,
290 breaker_sre_enabled: true,
291 max_concurrency: Some(1024),
292 request_timeout: Duration::from_secs(5),
293 shedding_enabled: true,
294 shedding_max_in_flight: Some(1024),
295 shedding_min_request_count: 20,
296 shedding_max_latency: Duration::from_millis(250),
297 ..Self::default()
298 }
299 }
300}
301
302#[cfg(all(feature = "resil", feature = "cache-redis"))]
304#[derive(Debug, Clone, PartialEq, Eq, Default)]
305pub enum RpcRateLimiterConfig {
306 #[default]
308 Disabled,
309 RedisToken(crate::resil::RedisTokenLimiterConfig),
311 RedisPeriod(crate::resil::RedisPeriodLimiterConfig),
313}