use std::time::Duration;
use crate::{HttpClientPolicy, ValidationError};
use crate::transport::policy::{JitterStrategy, RequestRateLimiter, RetryPolicy};
pub const DEFAULT_ORDERBOOK_USER_AGENT: &str =
concat!("cow-sdk-orderbook", "/", env!("CARGO_PKG_VERSION"));
pub const DEFAULT_SUBGRAPH_USER_AGENT: &str =
concat!("cow-sdk-subgraph", "/", env!("CARGO_PKG_VERSION"));
pub const DEFAULT_TRADING_USER_AGENT: &str =
concat!("cow-sdk-trading", "/", env!("CARGO_PKG_VERSION"));
pub const DEFAULT_IPFS_USER_AGENT: &str = concat!("cow-sdk-ipfs", "/", env!("CARGO_PKG_VERSION"));
pub const SUBGRAPH_MAX_RESPONSE_BYTES: usize = 2 * 1024 * 1024;
pub const IPFS_MAX_RESPONSE_BYTES: usize = 16 * 1024;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TransportPolicy {
client: HttpClientPolicy,
retry: RetryPolicy,
rate_limit: RequestRateLimiter,
}
impl Default for TransportPolicy {
fn default() -> Self {
Self::default_orderbook()
}
}
impl TransportPolicy {
#[must_use]
pub const fn new(
client: HttpClientPolicy,
retry: RetryPolicy,
rate_limit: RequestRateLimiter,
) -> Self {
Self {
client,
retry,
rate_limit,
}
}
#[must_use]
pub fn default_orderbook() -> Self {
Self {
client: HttpClientPolicy::new(DEFAULT_ORDERBOOK_USER_AGENT)
.expect("static orderbook user-agent must remain valid"),
retry: RetryPolicy::builder()
.jitter(JitterStrategy::decorrelated_process())
.build(),
rate_limit: RequestRateLimiter::default_orderbook(),
}
}
#[must_use]
pub fn default_subgraph() -> Self {
Self {
client: HttpClientPolicy::new(DEFAULT_SUBGRAPH_USER_AGENT)
.expect("static subgraph user-agent must remain valid")
.with_max_response_bytes(SUBGRAPH_MAX_RESPONSE_BYTES),
retry: RetryPolicy::builder()
.jitter(JitterStrategy::decorrelated_process())
.build(),
rate_limit: RequestRateLimiter::default_orderbook(),
}
}
#[must_use]
pub fn default_trading() -> Self {
Self {
client: HttpClientPolicy::new(DEFAULT_TRADING_USER_AGENT)
.expect("static trading user-agent must remain valid"),
retry: RetryPolicy::builder()
.jitter(JitterStrategy::decorrelated_process())
.build(),
rate_limit: RequestRateLimiter::default_orderbook(),
}
}
#[must_use]
pub fn default_ipfs() -> Self {
Self {
client: HttpClientPolicy::new(DEFAULT_IPFS_USER_AGENT)
.expect("static IPFS user-agent must remain valid")
.without_timeout()
.with_max_response_bytes(IPFS_MAX_RESPONSE_BYTES),
retry: RetryPolicy::no_retry(),
rate_limit: RequestRateLimiter::unlimited(),
}
}
#[must_use]
pub fn builder() -> TransportPolicyBuilder {
TransportPolicyBuilder::default()
}
#[must_use]
pub const fn client_policy(&self) -> &HttpClientPolicy {
&self.client
}
#[must_use]
pub const fn retry(&self) -> &RetryPolicy {
&self.retry
}
#[must_use]
pub const fn rate_limit(&self) -> &RequestRateLimiter {
&self.rate_limit
}
#[must_use]
pub const fn timeout(&self) -> Option<Duration> {
self.client.timeout()
}
#[must_use]
pub fn user_agent(&self) -> &str {
self.client.user_agent()
}
#[must_use]
pub fn with_client_policy(mut self, client: HttpClientPolicy) -> Self {
self.client = client;
self
}
#[must_use]
pub const fn with_retry(mut self, retry: RetryPolicy) -> Self {
self.retry = retry;
self
}
#[must_use]
pub fn with_rate_limit(mut self, rate_limit: RequestRateLimiter) -> Self {
self.rate_limit = rate_limit;
self
}
}
#[derive(Debug, Clone)]
pub struct TransportPolicyBuilder {
client: HttpClientPolicy,
retry: RetryPolicy,
rate_limit: RequestRateLimiter,
}
impl TransportPolicyBuilder {
#[must_use]
pub fn new() -> Self {
Self {
client: HttpClientPolicy::new(DEFAULT_ORDERBOOK_USER_AGENT)
.expect("static orderbook user-agent must remain valid"),
retry: RetryPolicy::builder()
.jitter(JitterStrategy::decorrelated_process())
.build(),
rate_limit: RequestRateLimiter::default_orderbook(),
}
}
#[must_use]
pub fn client_policy(mut self, client: HttpClientPolicy) -> Self {
self.client = client;
self
}
pub fn user_agent(mut self, user_agent: impl Into<String>) -> Result<Self, ValidationError> {
self.client = self.client.try_with_user_agent(user_agent)?;
Ok(self)
}
#[must_use]
pub fn timeout(mut self, timeout: Duration) -> Self {
self.client = self.client.with_timeout(timeout);
self
}
#[must_use]
pub const fn retry(mut self, retry: RetryPolicy) -> Self {
self.retry = retry;
self
}
#[must_use]
pub fn rate_limit(mut self, rate_limit: RequestRateLimiter) -> Self {
self.rate_limit = rate_limit;
self
}
#[must_use]
pub fn build(self) -> TransportPolicy {
TransportPolicy {
client: self.client,
retry: self.retry,
rate_limit: self.rate_limit,
}
}
}
impl Default for TransportPolicyBuilder {
fn default() -> Self {
Self::new()
}
}