tuwunel_service/fetcher/error.rs
1//! Internal failure reporting for federation fetches.
2//!
3//! Failures remain cloneable for broadcast to coalesced callers and retain the
4//! servers actually contacted for operator-facing diagnostics.
5
6use std::fmt;
7
8use ruma::OwnedServerName;
9use tuwunel_core::{err, smallvec::SmallVec};
10
11/// Servers contacted before a fetch gave up.
12///
13/// Inline storage is sized to the common candidate-pool budget.
14pub(super) type Attempted = SmallVec<[OwnedServerName; 3]>;
15
16/// Describes why a coalesced fetch produced no response.
17///
18/// The cloneable value is broadcast to every subscriber and converted to
19/// [`tuwunel_core::Error`] at the public boundary.
20#[derive(Clone, Debug)]
21pub(super) enum Failure {
22 /// The permitted attempts or rounds ended without a valid response.
23 NotFound {
24 /// Servers actually contacted before the fetch stopped.
25 attempted: Attempted,
26 },
27
28 /// No candidate servers were available to try.
29 NoCandidates,
30
31 /// Caller interest vanished or worker communication closed before a response arrived.
32 Cancelled,
33}
34
35impl fmt::Display for Failure {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 match self {
38 | Self::NoCandidates => write!(f, "no candidate servers available"),
39 | Self::Cancelled => write!(f, "fetch cancelled"),
40 | Self::NotFound { attempted } => {
41 write!(f, "event not found on any of {} servers", attempted.len())
42 },
43 }
44 }
45}
46
47impl From<Failure> for tuwunel_core::Error {
48 fn from(failure: Failure) -> Self { err!(Request(NotFound("{failure}"))) }
49}