dig_service/error.rs
1//! Service-level error types.
2//!
3//! Every fallible `Service` operation returns [`Result<T>`]
4//! = `Result<T, ServiceError>`. Errors are `Clone` (wrapping `anyhow::Error`
5//! in `Arc`) so they can fan out through broadcast channels or be bubbled
6//! through async traits without forcing the caller to stop.
7
8use std::sync::Arc;
9use std::time::Duration;
10
11use thiserror::Error;
12
13/// Convenience alias: `Result<T, ServiceError>`.
14pub type Result<T> = std::result::Result<T, ServiceError>;
15
16/// All failure modes of a running `Service`.
17#[derive(Error, Debug, Clone)]
18pub enum ServiceError {
19 /// The node's `pre_start` hook returned an error.
20 ///
21 /// No other lifecycle hooks are invoked after this — typical causes
22 /// are store open failures or journal replay errors.
23 #[error("pre_start failed: {0}")]
24 PreStartFailed(#[source] Arc<anyhow::Error>),
25
26 /// The node's `on_start` hook returned an error.
27 ///
28 /// `post_stop` is still invoked so resources opened in `pre_start`
29 /// have a chance to close.
30 #[error("on_start failed: {0}")]
31 OnStartFailed(#[source] Arc<anyhow::Error>),
32
33 /// The node's `run` hook returned an error.
34 ///
35 /// `on_stop` + `post_stop` are still invoked. The exit status's
36 /// `reason` is `ExitReason::RunError`.
37 #[error("run exited with error: {0}")]
38 RunFailed(#[source] Arc<anyhow::Error>),
39
40 /// The node's `on_stop` OR `post_stop` hook returned an error.
41 ///
42 /// Reported after `run` has returned; usually indicates a flush /
43 /// close failure.
44 #[error("on_stop failed: {0}")]
45 OnStopFailed(#[source] Arc<anyhow::Error>),
46
47 /// One or more tracked tasks did not exit within the shutdown deadline.
48 ///
49 /// The service aborts the laggards; this error is reported so operators
50 /// can see that shutdown was not fully graceful.
51 #[error("task registry deadline exceeded ({deadline:?}); {pending} tasks aborted")]
52 ShutdownDeadlineExceeded {
53 /// The deadline that was exceeded.
54 deadline: Duration,
55 /// How many tasks were still alive when the deadline fired.
56 pending: usize,
57 },
58
59 /// `start()` was called on a Service that has already run.
60 ///
61 /// A `Service` is single-shot — once started, build a new one.
62 #[error("service is already running")]
63 AlreadyRunning,
64
65 /// `start()` was called on a Service that has already stopped.
66 ///
67 /// Reserved for future re-entry protections; currently unreachable.
68 #[error("service has already stopped")]
69 AlreadyStopped,
70}