titanrt 0.7.0

Typed reactive runtime for real-time systems
Documentation
use std::{net::IpAddr, str::FromStr, sync::Arc, time::Duration};

use reqwest::Client;
use serde::{Deserialize, Serialize};
use tokio::runtime::Runtime;

use crate::connector::{
    errors::StreamError,
    features::shared::clients_map::{ClientInitializer, SpecificClient},
};

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ReqwestClientSpec {
    pub pool_max_idle_per_host: usize,
    pub pool_idle_timeout_sec: u64,
    pub request_timeout_ms: Option<u64>,
}

#[derive(Clone)]
pub struct ReqwestClient(pub Client);

impl ClientInitializer<ReqwestClientSpec> for ReqwestClient {
    fn init(
        cfg: &SpecificClient<ReqwestClientSpec>,
        _rt: Option<Arc<Runtime>>,
    ) -> anyhow::Result<Self> {
        let mut builder = reqwest::ClientBuilder::new()
            .pool_max_idle_per_host(cfg.spec.pool_max_idle_per_host)
            .pool_idle_timeout(Duration::from_secs(cfg.spec.pool_idle_timeout_sec))
            .tcp_nodelay(true);

        if let Some(t) = cfg.spec.request_timeout_ms {
            builder = builder.timeout(Duration::from_millis(t));
        }

        if let Some(ip) = cfg.ip.as_deref() {
            let ip = IpAddr::from_str(ip).map_err(|e| {
                StreamError::Unknown(anyhow::anyhow!("[ReqwestClient] IP parse error: {e}"))
            })?;

            builder = builder.local_address(ip)
        }

        let client = builder.build().map_err(|e| {
            StreamError::Unknown(anyhow::anyhow!("[ReqwestClient] Build error: {e}"))
        })?;

        let conn = ReqwestClient(client);
        Ok(conn)
    }
}