allora_core/
error.rs

1//! Error types and result alias for Allora.
2//!
3//! # Overview
4//! The library uses a single enum [`Error`] to classify failures across
5//! processors, routing, aggregation, serialization, and miscellaneous cases.
6//! A crate-wide `Result<T>` type alias simplifies return signatures.
7//!
8//! # Goals
9//! * Lightweight – no deep error type hierarchy.
10//! * Human-friendly `Display` messages via `thiserror`.
11//! * Extensible – new variants can be added in a non-breaking way (add to end).
12//!
13//! # When to Use Each Variant
14//! * `Processor` – logic inside a processor failed (validation, transformation).
15//! * `Routing` – route selection / content-based routing issues (no match, invalid path).
16//! * `Aggregation` – aggregator state or completion failures.
17//! * `Serialization` – encoding/decoding payload/header data.
18//! * `Other` – fallback / miscellaneous; prefer creating a dedicated variant when patterns emerge.
19//!
20//! # Adding New Variants
21//! Add at the end of the enum to avoid changing numeric discriminants (though they are
22//! not relied upon externally). Provide a clear `#[error(...)]` message and (optionally)
23//! a convenience constructor method.
24//!
25//! # Example
26//! ```no_run
27//! use allora_core::{Error, Result};
28//! fn fallible() -> Result<()> { Err(Error::other("boom")) }
29//! assert!(fallible().is_err());
30//! ```
31//! ```
32//! use allora_core::{Result, Error};
33//! fn do_work(ok: bool) -> Result<()> {
34//!     if ok { Ok(()) } else { Err(Error::processor("failed logic")) }
35//! }
36//! assert!(do_work(true).is_ok());
37//! assert!(matches!(do_work(false), Err(Error::Processor(_))));
38//! ```
39//! ```rust
40//! use allora_core::{Result, Error};
41//! fn demo() -> Result<()> { Ok(()) }
42//! ```
43//! ```rust
44//! use allora_core::{Result, Error};
45//! fn demo() -> Result<()> { Ok(()) }
46//! ```
47
48use thiserror::Error;
49
50pub type Result<T, E = Error> = std::result::Result<T, E>;
51
52#[derive(Debug, Error)]
53pub enum Error {
54    #[error("runtime error: {0}")]
55    Runtime(String),
56    #[error("processor error: {0}")]
57    /// Errors originating from processor logic (validation, transformation, enrichment).
58    Processor(String),
59    #[error("routing error: {0}")]
60    /// Routing / selection failures (no content-based router match, invalid endpoint path).
61    Routing(String),
62    #[error("aggregation error: {0}")]
63    /// Aggregation pattern related failures (missing bucket, premature completion, etc.).
64    Aggregation(String),
65    #[error("serialization error: {0}")]
66    /// (De)serialization failures for payloads or headers (JSON, bytes conversion, etc.).
67    Serialization(String),
68    #[error("unknown error: {0}")]
69    /// Catch-all variant for uncategorized errors; prefer creating a dedicated variant over time.
70    Other(String),
71}
72
73impl Error {
74    /// Convenience: create an `Other` error.
75    pub fn other<S: Into<String>>(s: S) -> Self {
76        Self::Other(s.into())
77    }
78    /// Convenience: create an `Runtime` error.
79    pub fn runtime<S: Into<String>>(s: S) -> Self {
80        Self::Runtime(s.into())
81    }
82    /// Convenience: create a `Processor` error.
83    pub fn processor<S: Into<String>>(s: S) -> Self {
84        Self::Processor(s.into())
85    }
86    /// Convenience: create a `Routing` error.
87    pub fn routing<S: Into<String>>(s: S) -> Self {
88        Self::Routing(s.into())
89    }
90    /// Convenience: create an `Aggregation` error.
91    pub fn aggregation<S: Into<String>>(s: S) -> Self {
92        Self::Aggregation(s.into())
93    }
94    /// Convenience: create a `Serialization` error.
95    pub fn serialization<S: Into<String>>(s: S) -> Self {
96        Self::Serialization(s.into())
97    }
98}