Skip to main content

ironflow_sdk/
builder.rs

1//! Builder pattern for [`IronflowClient`] with retry and rate-limit configuration.
2
3use std::time::Duration;
4
5use bytes::Bytes;
6
7use crate::client::{ClientConfig, IronflowClient};
8use crate::rate_limit::RateLimiter;
9use crate::retry::RetryConfig;
10
11/// Result of downloading an artifact.
12///
13/// # Examples
14///
15/// ```
16/// use ironflow_sdk::client::ArtifactDownload;
17/// use bytes::Bytes;
18///
19/// let download = ArtifactDownload {
20///     bytes: Bytes::from_static(b"hello"),
21///     content_type: "text/plain".to_string(),
22///     sha256: "abc123".to_string(),
23/// };
24/// assert_eq!(download.bytes.len(), 5);
25/// ```
26#[derive(Debug, Clone)]
27pub struct ArtifactDownload {
28    /// Raw artifact bytes.
29    pub bytes: Bytes,
30    /// MIME type recorded at upload time.
31    pub content_type: String,
32    /// SHA-256 digest of the artifact content (hex-encoded).
33    pub sha256: String,
34}
35
36/// Builder for [`IronflowClient`] with retry and rate-limit configuration.
37///
38/// # Examples
39///
40/// ```
41/// use ironflow_sdk::ClientBuilder;
42///
43/// let client = ClientBuilder::new("https://ironflow.example.com", "my-api-key")
44///     .with_max_retries(5)
45///     .with_rate_limit(false)
46///     .build();
47/// ```
48pub struct ClientBuilder {
49    config: ClientConfig,
50    retry: RetryConfig,
51    rate_limit_enabled: bool,
52}
53
54impl ClientBuilder {
55    /// Create a builder with defaults (3 retries, rate-limit enabled).
56    ///
57    /// # Examples
58    ///
59    /// ```
60    /// use ironflow_sdk::ClientBuilder;
61    ///
62    /// let builder = ClientBuilder::new("https://ironflow.example.com", "key");
63    /// ```
64    pub fn new(base_url: &str, api_key: &str) -> Self {
65        Self {
66            config: ClientConfig {
67                base_url: base_url.trim_end_matches('/').to_string(),
68                api_key: api_key.to_string(),
69                timeout: Duration::from_secs(30),
70            },
71            retry: RetryConfig::default(),
72            rate_limit_enabled: true,
73        }
74    }
75
76    /// Set the maximum number of retry attempts.
77    ///
78    /// # Examples
79    ///
80    /// ```
81    /// use ironflow_sdk::ClientBuilder;
82    ///
83    /// let client = ClientBuilder::new("https://ironflow.example.com", "key")
84    ///     .with_max_retries(5)
85    ///     .build();
86    /// ```
87    pub fn with_max_retries(mut self, n: u32) -> Self {
88        self.retry.max_retries = n;
89        self
90    }
91
92    /// Set the HTTP request timeout.
93    ///
94    /// # Examples
95    ///
96    /// ```
97    /// use ironflow_sdk::ClientBuilder;
98    /// use std::time::Duration;
99    ///
100    /// let client = ClientBuilder::new("https://ironflow.example.com", "key")
101    ///     .with_timeout(Duration::from_secs(60))
102    ///     .build();
103    /// ```
104    pub fn with_timeout(mut self, timeout: Duration) -> Self {
105        self.config.timeout = timeout;
106        self
107    }
108
109    /// Enable or disable client-side rate limiting.
110    ///
111    /// When enabled (the default), the client waits for the `Retry-After`
112    /// window to expire before sending the next request after a 429.
113    ///
114    /// # Examples
115    ///
116    /// ```
117    /// use ironflow_sdk::ClientBuilder;
118    ///
119    /// let client = ClientBuilder::new("https://ironflow.example.com", "key")
120    ///     .with_rate_limit(false)
121    ///     .build();
122    /// ```
123    pub fn with_rate_limit(mut self, enabled: bool) -> Self {
124        self.rate_limit_enabled = enabled;
125        self
126    }
127
128    /// Build the [`IronflowClient`].
129    ///
130    /// # Panics
131    ///
132    /// Panics if the API key contains characters invalid for HTTP headers.
133    ///
134    /// # Examples
135    ///
136    /// ```
137    /// use ironflow_sdk::ClientBuilder;
138    ///
139    /// let client = ClientBuilder::new("https://ironflow.example.com", "key").build();
140    /// ```
141    pub fn build(self) -> IronflowClient {
142        let rate_limiter = if self.rate_limit_enabled {
143            RateLimiter::new()
144        } else {
145            RateLimiter::disabled()
146        };
147        IronflowClient::from_config_with_retry(self.config, self.retry, rate_limiter)
148    }
149}