Skip to main content

ferroid_tonic_core/common/
error.rs

1//! Error types for the ID generation service.
2//!
3//! This module defines the central `Error` enum, which captures all recoverable
4//! and reportable error cases within the ID generation system. It implements
5//! `From<Error>` for `tonic::Status` to enable seamless gRPC error propagation
6//! to clients with appropriate status codes and messages.
7//!
8//! ## Error Cases
9//! - `ChannelError`: An internal communication failure between tasks or
10//!   workers.
11//! - `IdGeneration`: An error occurred during ID creation (via the `ferroid`
12//!   generator).
13//! - `RequestCancelled`: The client canceled the request mid-flight.
14//! - `InvalidRequest`: The client request was malformed or exceeded bounds.
15//! - `ServiceShutdown`: A request arrived while the service was shutting down.
16
17use tonic::Status;
18
19pub type Result<T> = core::result::Result<T, Error>;
20
21/// Unified error type for the ID generation service.
22#[derive(Clone, thiserror::Error, Debug)]
23#[non_exhaustive]
24pub enum Error {
25    /// Internal channel send/receive failure (e.g., closed or full channel).
26    #[error("Channel error: {context}")]
27    ChannelError { context: String },
28
29    /// Underlying Snowflake ID generation failed. This is currently infallible,
30    /// but kept as a placeholder if the generator type yields an error.
31    #[error("ID error: {0:?}")]
32    IdGeneration(#[from] core::convert::Infallible),
33
34    /// The client aborted the request.
35    #[error("Request cancelled by client")]
36    RequestCancelled,
37
38    /// The client request was invalid or exceeded constraints.
39    #[error("Invalid request: {reason}")]
40    InvalidRequest { reason: String },
41
42    /// The service is in the process of shutting down.
43    #[error("Service is shutting down")]
44    ServiceShutdown,
45}
46
47impl From<Error> for Status {
48    fn from(err: Error) -> Self {
49        match err {
50            Error::ChannelError { context } => Self::internal(format!("Channel error: {context}")),
51            Error::IdGeneration(e) => Self::internal(format!("ID generation error: {e:?}")),
52            Error::RequestCancelled => Self::cancelled("Request was cancelled"),
53            Error::InvalidRequest { reason } => Self::invalid_argument(reason),
54            Error::ServiceShutdown => Self::unavailable("Service is shutting down"),
55        }
56    }
57}