tencentcloud_sms/
client.rs1use crate::{
2 config::ClientConfig,
3 credential::Credential,
4 error::{SmsError, SmsResult},
5};
6use reqwest::Client as HttpClient;
7use std::time::Duration;
8
9pub(crate) const API_VERSION: &str = "2021-01-11";
10
11#[derive(Clone)]
12pub struct SmsClient {
13 pub(crate) credential: Credential,
14 pub(crate) config: ClientConfig,
15 pub(crate) http_client: HttpClient,
16}
17
18impl SmsClient {
19 pub fn new(credential: Credential, config: ClientConfig) -> SmsResult<Self> {
29 config.validate()?;
31
32 let mut builder = HttpClient::builder()
33 .timeout(config.timeout)
34 .pool_idle_timeout(Duration::from_secs(90))
35 .pool_max_idle_per_host(10);
36
37 if let Some(proxy_url) = &config.proxy {
38 let proxy = reqwest::Proxy::all(proxy_url)
39 .map_err(|e| SmsError::Configuration(format!("代理配置错误: {}", e)))?;
40 builder = builder.proxy(proxy);
41 }
42
43 let http_client = builder
44 .build()
45 .map_err(|e| SmsError::Configuration(format!("HTTP客户端构建失败: {}", e)))?;
46
47 Ok(Self {
48 credential,
49 config,
50 http_client,
51 })
52 }
53
54 pub(crate) fn calculate_backoff(&self, attempt: u64, suggested: Option<Duration>) -> Duration {
58 if let Some(delay) = suggested {
60 return delay;
61 }
62
63 let retry_config = match &self.config.retry {
64 Some(c) => c,
65 None => return Duration::from_secs(1),
66 };
67
68 let mut delay = retry_config.initial_backoff.as_millis() as f64
70 * retry_config.backoff_multiplier.powi(attempt as i32 - 1);
71
72 if retry_config.add_jitter {
74 use rand::Rng;
75 let jitter = rand::rng().random_range(0.75..=1.25);
76 delay *= jitter;
77 }
78
79 Duration::from_millis(delay.min(retry_config.max_backoff.as_millis() as f64) as u64)
81 }
82}