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}