Skip to main content

ruststream_fred/
error.rs

1//! Error type returned by Redis broker operations.
2
3use std::error::Error as StdError;
4
5use thiserror::Error;
6
7/// Errors surfaced by the Redis broker implementation.
8#[derive(Debug, Error)]
9#[non_exhaustive]
10pub enum RedisError {
11    /// Failed to establish or use the underlying `fred` connection.
12    #[error("redis connection error: {0}")]
13    Connect(#[source] Box<dyn StdError + Send + Sync>),
14
15    /// Failed to publish (`XADD`) a message to a stream.
16    #[error("redis publish error: {0}")]
17    Publish(#[source] Box<dyn StdError + Send + Sync>),
18
19    /// Failed to open a subscription (consumer-group creation or the first read).
20    #[error("redis subscribe error: {0}")]
21    Subscribe(#[source] Box<dyn StdError + Send + Sync>),
22
23    /// A stream read (`XREADGROUP` / `XAUTOCLAIM`) or acknowledgement (`XACK`) failed.
24    #[error("redis stream error: {0}")]
25    Stream(#[source] Box<dyn StdError + Send + Sync>),
26
27    /// The operation ran through a handle aliasing a connection that was already shut down
28    /// ([`ConnectedBroker::shutdown`](ruststream::ConnectedBroker::shutdown)).
29    ///
30    /// The lifecycle ladder makes misuse by the owner of the connected broker a compile error;
31    /// publishers handed out before the shutdown outlive it, so their operations report this
32    /// instead of running against a dead pool.
33    #[error("the redis broker connection is shut down")]
34    ShutDown,
35
36    /// `begin_transaction` was called while a transaction is already open on this publisher handle.
37    #[error("a transaction is already open on this publisher handle")]
38    TransactionBusy,
39
40    /// `commit` or `abort` was called with no open transaction on this publisher handle.
41    #[error("no transaction is open on this publisher handle")]
42    NoTransaction,
43
44    /// The supplied subscription descriptor combines fields in a way the broker cannot honour
45    /// (for example a [`RedisStream`](crate::RedisStream) with no consumer group, or a bare-string
46    /// subscription with no broker-wide default group).
47    #[error("invalid subscribe options: {0}")]
48    InvalidOptions(String),
49
50    /// The connected server is older than the subscription's read mode needs.
51    ///
52    /// [`RedisStream::claiming`](crate::RedisStream::claiming) issues `XREADGROUP ... CLAIM`,
53    /// which Redis 8.4.0 added. The check runs where the subscription resolves against the
54    /// connected broker, once and before the first read, so the service fails at startup with
55    /// both versions named instead of meeting a syntax error on its first message.
56    ///
57    /// The message is the whole error: it already names the subscription, the mode and the two
58    /// versions, and a prefix would only repeat them.
59    #[error("{0}")]
60    ServerTooOld(String),
61
62    /// A window of a `.pipeline()` subscription failed to send what it owed.
63    ///
64    /// Reported once, on the subscription's delivery stream, and the message names the
65    /// subscription, how many commands the flush carried and how many failed. On the forms that
66    /// settle, the entries whose settles failed stay pending and are delivered again.
67    #[error("{0}")]
68    Flush(String),
69}
70
71impl RedisError {
72    /// Wraps a `fred` error as a [`RedisError::Stream`].
73    pub(crate) fn stream(err: fred::error::Error) -> Self {
74        Self::Stream(Box::new(err))
75    }
76
77    /// Wraps a `fred` error as a [`RedisError::Subscribe`].
78    pub(crate) fn subscribe(err: fred::error::Error) -> Self {
79        Self::Subscribe(Box::new(err))
80    }
81
82    /// Wraps a `fred` error as a [`RedisError::Publish`].
83    pub(crate) fn publish(err: fred::error::Error) -> Self {
84        Self::Publish(Box::new(err))
85    }
86}