use std::{
fmt::{self, Debug},
num::NonZeroUsize,
time::Duration,
};
use matrix_sdk_common::debug::DebugStructExt;
use crate::http_client::DEFAULT_REQUEST_TIMEOUT;
#[derive(Copy, Clone)]
pub struct RequestConfig {
pub(crate) timeout: Option<Duration>,
pub(crate) read_timeout: Option<Duration>,
pub(crate) retry_limit: Option<usize>,
pub(crate) max_retry_time: Option<Duration>,
pub(crate) max_concurrent_requests: Option<NonZeroUsize>,
pub(crate) force_auth: bool,
pub(crate) skip_auth: bool,
}
#[cfg(not(tarpaulin_include))]
impl Debug for RequestConfig {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self {
timeout,
read_timeout,
retry_limit,
max_retry_time: retry_timeout,
force_auth,
max_concurrent_requests,
skip_auth: skip_optional_auth,
} = self;
let mut res = fmt.debug_struct("RequestConfig");
res.field("timeout", timeout)
.maybe_field("read_timeout", read_timeout)
.maybe_field("retry_limit", retry_limit)
.maybe_field("max_retry_time", retry_timeout)
.maybe_field("max_concurrent_requests", max_concurrent_requests);
if *force_auth {
res.field("force_auth", &true);
}
if *skip_optional_auth {
res.field("skip_optional_auth", &true);
}
res.finish()
}
}
impl Default for RequestConfig {
fn default() -> Self {
Self {
timeout: Some(DEFAULT_REQUEST_TIMEOUT),
read_timeout: None,
retry_limit: Default::default(),
max_retry_time: Default::default(),
max_concurrent_requests: Default::default(),
force_auth: false,
skip_auth: false,
}
}
}
impl RequestConfig {
#[must_use]
pub fn new() -> Self {
Default::default()
}
#[must_use]
pub fn short_retry() -> Self {
Self::default().retry_limit(3)
}
#[must_use]
pub fn disable_retry(mut self) -> Self {
self.retry_limit = Some(0);
self
}
#[must_use]
pub fn retry_limit(mut self, retry_limit: usize) -> Self {
self.retry_limit = Some(retry_limit);
self
}
#[must_use]
pub fn max_concurrent_requests(mut self, limit: Option<NonZeroUsize>) -> Self {
self.max_concurrent_requests = limit;
self
}
#[must_use]
pub fn timeout(mut self, timeout: impl Into<Option<Duration>>) -> Self {
self.timeout = timeout.into();
self
}
#[must_use]
pub fn read_timeout(mut self, timeout: impl Into<Option<Duration>>) -> Self {
self.read_timeout = timeout.into();
self
}
#[must_use]
pub fn max_retry_time(mut self, retry_timeout: Duration) -> Self {
self.max_retry_time = Some(retry_timeout);
self
}
#[must_use]
pub fn force_auth(mut self) -> Self {
self.force_auth = true;
self
}
#[must_use]
pub fn skip_auth(mut self) -> Self {
self.skip_auth = true;
self
}
}
#[cfg(test)]
mod tests {
use std::time::Duration;
use super::RequestConfig;
#[test]
fn smoketest() {
let cfg = RequestConfig::new()
.force_auth()
.max_retry_time(Duration::from_secs(32))
.retry_limit(4)
.timeout(Duration::from_secs(600))
.read_timeout(Duration::from_secs(10));
assert!(cfg.force_auth);
assert_eq!(cfg.retry_limit, Some(4));
assert_eq!(cfg.max_retry_time, Some(Duration::from_secs(32)));
assert_eq!(cfg.timeout, Some(Duration::from_secs(600)));
assert_eq!(cfg.read_timeout, Some(Duration::from_secs(10)));
}
#[test]
fn testing_retry_settings() {
let mut cfg = RequestConfig::new();
assert_eq!(cfg.retry_limit, None);
cfg = cfg.retry_limit(10);
assert_eq!(cfg.retry_limit, Some(10));
cfg = cfg.disable_retry();
assert_eq!(cfg.retry_limit, Some(0));
let cfg = RequestConfig::short_retry();
assert_eq!(cfg.retry_limit, Some(3));
}
}