reifydb_runtime/
shutdown.rs1use std::fmt;
5
6use reifydb_value::{
7 Result,
8 error::{Diagnostic, Error},
9 fragment::Fragment,
10};
11
12pub trait Shutdown {
13 fn shutdown(&self) -> Result<()>;
14}
15
16pub fn shutdown_failed(subsystem: impl fmt::Display, reason: impl fmt::Display) -> Diagnostic {
17 Diagnostic {
18 code: "SUB_004".to_string(),
19 rql: None,
20 message: format!("{} subsystem shutdown failed: {}", subsystem, reason),
21 column: None,
22 fragment: Fragment::None,
23 label: None,
24 help: None,
25 notes: vec![],
26 cause: None,
27 operator_chain: None,
28 }
29}
30
31pub struct ShutdownErrors {
32 owner: &'static str,
33 failed: Vec<String>,
34}
35
36impl ShutdownErrors {
37 pub fn new(owner: &'static str) -> Self {
38 Self {
39 owner,
40 failed: Vec::new(),
41 }
42 }
43
44 pub fn step(&mut self, part: &'static str, result: Result<()>) {
45 let Err(err) = result else {
46 return;
47 };
48 let diagnostic = err.diagnostic();
49 if diagnostic.code == "SUB_004" {
50 self.failed.extend(diagnostic.notes.into_iter().map(|note| format!("{part}/{note}")));
51 } else {
52 self.failed.push(format!("{part}: {}", diagnostic.message));
53 }
54 }
55
56 pub fn fail(&mut self, part: &'static str, reason: impl fmt::Display) {
57 self.failed.push(format!("{part}: {reason}"));
58 }
59
60 pub fn finish(self) -> Result<()> {
61 if self.failed.is_empty() {
62 return Ok(());
63 }
64 let reason = format!("{} parts failed", self.failed.len());
65 Err(Error(Box::new(Diagnostic {
66 notes: self.failed,
67 ..shutdown_failed(self.owner, reason)
68 })))
69 }
70}