Skip to main content

hyperi_rustlib/concurrency/
error.rs

1// Project:   hyperi-rustlib
2// File:      src/concurrency/error.rs
3// Purpose:   Error types for the three async concurrency primitives
4// Language:  Rust
5//
6// License:   BUSL-1.1
7// Copyright: (c) 2026 HYPERI PTY LIMITED
8
9//! Error types for [`crate::concurrency`] primitives.
10//!
11//! Three concrete error enums, one per primitive:
12//! [`SinkError`] for `BackgroundSink`, [`TickError`] for `PeriodicWorker`,
13//! [`ActorError`] for `ActorHandle`. Plus [`DrainError`] for `SinkDrain`
14//! implementations to report backend failures back to the actor.
15
16use std::error::Error as StdError;
17
18use thiserror::Error;
19
20/// Errors returned by [`super::BackgroundSink`] push / flush operations.
21#[derive(Debug, Error)]
22pub enum SinkError {
23    /// Queue full and `Overflow::Drop` was selected -- message discarded
24    /// and the sink's `dropped` counter incremented.
25    #[error("background sink queue full (overflow=drop policy)")]
26    Overflow,
27
28    /// The background actor has exited (shutdown cancelled or all
29    /// senders dropped). No further pushes will succeed.
30    #[error("background sink actor has exited")]
31    Closed,
32
33    /// A drain implementation reported an error during a batch write.
34    /// The actor logs + counts these and continues; this variant is
35    /// only surfaced if the caller asks the sink for a propagated error
36    /// (rare -- drain failures are usually observed via the
37    /// `<prefix>_write_errors_total` metric).
38    #[error("drain failure: {0}")]
39    Drain(#[from] DrainError),
40}
41
42/// Errors returned by [`super::SinkDrain`] implementations.
43///
44/// Drain failures are logged + counted but do NOT terminate the actor.
45/// The actor continues draining subsequent batches. If a drain
46/// consistently fails, operators see rising `<prefix>_write_errors_total`
47/// and the `<prefix>_pending` gauge climbing toward the queue cap.
48#[derive(Debug, Error)]
49pub enum DrainError {
50    /// Standard library I/O error (file writes, syscalls, etc.).
51    #[error("io: {0}")]
52    Io(#[from] std::io::Error),
53
54    /// Backend-specific error wrapped as `Box<dyn Error>`. Backends
55    /// (Kafka, Redis, HTTP) convert their native error types into this
56    /// via `From` impls in their own modules.
57    #[error("backend: {0}")]
58    Backend(Box<dyn StdError + Send + Sync>),
59}
60
61/// Errors returned by [`super::PeriodicTask`] tick implementations.
62///
63/// Tick errors are logged at WARN and do NOT terminate the worker --
64/// the next tick still fires. Consumers wanting fail-fast must return
65/// `Ok(())` from `tick` and surface their failure differently (e.g.
66/// via a `failed: AtomicBool` flag the parent process polls).
67#[derive(Debug, Error)]
68pub enum TickError {
69    /// Generic error wrapper. Most tick implementations only have one
70    /// failure mode and convert their native error type into this.
71    #[error("{0}")]
72    Generic(Box<dyn StdError + Send + Sync>),
73}
74
75/// Errors returned by [`super::ActorHandle`] send operations.
76#[derive(Debug, Error)]
77pub enum ActorError {
78    /// `try_send` saw a full command queue. Caller chooses whether to
79    /// drop, retry, or escalate.
80    #[error("actor command queue full")]
81    Full,
82
83    /// The actor task has exited. No further commands accepted.
84    #[error("actor has exited")]
85    Closed,
86}