Skip to main content

aspero_engine/
options.rs

1//! Per-call options: how patient one caller is, independent of providers'
2//! own policies.
3
4use std::time::Duration;
5
6use aspero_core::ResiliencePolicy;
7
8/// How patient a caller is. The default is a batch caller's: providers'
9/// own policies, retries and all. Set on an engine view with
10/// [`Engine::with_options`](crate::Engine::with_options); views share the
11/// cache, pacing and requests in flight.
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
13#[non_exhaustive]
14pub struct CallOptions {
15    /// Caps each provider's overall deadline, retries included.
16    pub deadline: Option<Duration>,
17    /// Caps each provider's retries.
18    pub max_retries: Option<u32>,
19    /// Answers from the cache only, however old; what it lacks fails as
20    /// [`Error::Offline`](aspero_core::Error::Offline).
21    pub offline: bool,
22}
23
24impl CallOptions {
25    /// Someone is waiting: give up on a provider within a few seconds and
26    /// fall back (to the next provider, or a stale cached answer).
27    pub fn interactive() -> Self {
28        CallOptions {
29            deadline: Some(Duration::from_secs(8)),
30            max_retries: Some(1),
31            offline: false,
32        }
33    }
34
35    /// Answers from the cache only.
36    pub fn offline() -> Self {
37        CallOptions {
38            offline: true,
39            ..CallOptions::default()
40        }
41    }
42
43    /// `policy`, capped by these options.
44    pub(crate) fn apply(&self, policy: &ResiliencePolicy) -> ResiliencePolicy {
45        let mut p = policy.clone();
46        if let Some(d) = self.deadline {
47            p.deadline = p.deadline.min(d);
48            p.attempt_timeout = p.attempt_timeout.min(d);
49        }
50        if let Some(r) = self.max_retries {
51            p.max_retries = p.max_retries.min(r);
52        }
53        p
54    }
55}