Skip to main content

nodedb_cluster/subsystem/
errors.rs

1// SPDX-License-Identifier: BUSL-1.1
2
3//! Error types for the subsystem bootstrap and shutdown lifecycle.
4
5use thiserror::Error;
6
7/// Error produced during topo-sort of the subsystem dependency graph.
8#[derive(Debug, Error)]
9pub enum TopoError {
10    /// A cycle was detected in the dependency graph.
11    ///
12    /// `cycle` lists the subsystem names forming the cycle in order.
13    #[error("dependency cycle detected: {}", cycle.join(" -> "))]
14    Cycle { cycle: Vec<&'static str> },
15
16    /// A subsystem listed a dependency that is not registered.
17    #[error("subsystem {subsystem:?} depends on unknown subsystem {dependency:?}")]
18    UnknownDependency {
19        subsystem: &'static str,
20        dependency: &'static str,
21    },
22}
23
24/// Error produced while starting one or more subsystems.
25#[derive(Debug, Error)]
26pub enum BootstrapError {
27    /// The dependency graph could not be resolved.
28    #[error("subsystem dependency resolution failed: {0}")]
29    TopoSort(#[from] TopoError),
30
31    /// A subsystem failed during its `start` call.
32    #[error("subsystem {name:?} failed to start: {cause}")]
33    SubsystemStart {
34        name: &'static str,
35        #[source]
36        cause: Box<dyn std::error::Error + Send + Sync + 'static>,
37    },
38
39    /// One or more previously-started subsystems could not be shut down
40    /// cleanly after a sibling failure. The original start failure is
41    /// included as `start_error`.
42    #[error(
43        "subsystem {name:?} failed to start; cleanup of already-started \
44         subsystems also encountered errors: {shutdown_errors:?}"
45    )]
46    StartAndShutdownFailure {
47        name: &'static str,
48        shutdown_errors: Vec<ShutdownError>,
49    },
50}
51
52/// Error produced during graceful shutdown of a subsystem.
53#[derive(Debug, Error)]
54pub enum ShutdownError {
55    /// The subsystem did not stop within the allotted deadline.
56    #[error("subsystem {name:?} did not stop before the shutdown deadline")]
57    DeadlineExceeded { name: &'static str },
58
59    /// The subsystem's task panicked during shutdown.
60    #[error("subsystem {name:?} panicked during shutdown")]
61    Panicked { name: &'static str },
62
63    /// The subsystem reported an error during shutdown.
64    #[error("subsystem {name:?} shutdown error: {cause}")]
65    SubsystemError {
66        name: &'static str,
67        #[source]
68        cause: Box<dyn std::error::Error + Send + Sync + 'static>,
69    },
70}
71
72impl From<BootstrapError> for crate::error::ClusterError {
73    fn from(e: BootstrapError) -> Self {
74        crate::error::ClusterError::Storage {
75            detail: e.to_string(),
76        }
77    }
78}
79
80impl From<ShutdownError> for crate::error::ClusterError {
81    fn from(e: ShutdownError) -> Self {
82        crate::error::ClusterError::Storage {
83            detail: e.to_string(),
84        }
85    }
86}
87
88impl From<TopoError> for crate::error::ClusterError {
89    fn from(e: TopoError) -> Self {
90        crate::error::ClusterError::Storage {
91            detail: e.to_string(),
92        }
93    }
94}