|
1 | 1 | use std::sync::Arc;
|
2 | 2 |
|
3 | 3 | use parking_lot::Mutex;
|
4 |
| -use tokio::sync::mpsc; |
| 4 | +use tokio::sync::oneshot; |
5 | 5 |
|
6 | 6 | use crate::errors::report_error_sync;
|
7 | 7 |
|
8 |
| -// Used by the database to signal it has encountered a fatal error. |
| 8 | +/// Used by the database to signal it has encountered a fatal error. |
9 | 9 | #[derive(Clone)]
|
10 | 10 | pub struct ShutdownSignal {
|
11 |
| - shutdown_tx: Option<Arc<Mutex<Option<mpsc::UnboundedSender<ShutdownMessage>>>>>, |
12 |
| - instance_name: String, |
13 |
| - generation_id: u64, |
| 11 | + mode: Mode, |
14 | 12 | }
|
15 | 13 |
|
16 |
| -#[derive(Debug)] |
17 |
| -pub struct ShutdownMessage { |
18 |
| - pub error: anyhow::Error, |
19 |
| - pub instance_name: String, |
20 |
| - pub generation_id: u64, |
| 14 | +/// Indicates what to do when an error is reported. |
| 15 | +#[derive(Clone)] |
| 16 | +enum Mode { |
| 17 | + Panic, |
| 18 | + /// If the `Option` inside the mutex is `Some`, the next fatal error will be |
| 19 | + /// sent to that sender. Otherwise, signalling will do nothing (under the |
| 20 | + /// presumption that an earlier error was reported and removed the sender). |
| 21 | + Notify(Arc<Mutex<Option<oneshot::Sender<anyhow::Error>>>>), |
21 | 22 | }
|
22 | 23 |
|
23 | 24 | impl ShutdownSignal {
|
24 |
| - pub fn new( |
25 |
| - shutdown_tx: mpsc::UnboundedSender<ShutdownMessage>, |
26 |
| - instance_name: String, |
27 |
| - generation_id: u64, |
28 |
| - ) -> Self { |
| 25 | + /// Creates a new ShutdownSignal that sends the first encountered error to |
| 26 | + /// the provided oneshot sender. |
| 27 | + pub fn new(shutdown_tx: oneshot::Sender<anyhow::Error>) -> Self { |
29 | 28 | Self {
|
30 |
| - shutdown_tx: Some(Arc::new(Mutex::new(Some(shutdown_tx)))), |
31 |
| - instance_name, |
32 |
| - generation_id, |
| 29 | + mode: Mode::Notify(Arc::new(Mutex::new(Some(shutdown_tx)))), |
33 | 30 | }
|
34 | 31 | }
|
35 | 32 |
|
| 33 | + /// Signals that an instance has encountered a fatal error and needs to be |
| 34 | + /// shut down. |
36 | 35 | pub fn signal(&self, mut fatal_error: anyhow::Error) {
|
37 | 36 | report_error_sync(&mut fatal_error);
|
38 |
| - if let Some(ref shutdown_tx_mutex) = self.shutdown_tx { |
39 |
| - let Some(shutdown_tx) = shutdown_tx_mutex.lock().take() else { |
40 |
| - // A shutdown message has already been sent for this instance. Do nothing. |
41 |
| - return; |
42 |
| - }; |
43 |
| - _ = shutdown_tx.send(ShutdownMessage { |
44 |
| - error: fatal_error, |
45 |
| - instance_name: self.instance_name.clone(), |
46 |
| - generation_id: self.generation_id, |
47 |
| - }); |
48 |
| - } else { |
49 |
| - // We don't anyone to shutdown signal configured. Just panic. |
50 |
| - panic!("Shutting down due to fatal error: {}", fatal_error); |
| 37 | + match &self.mode { |
| 38 | + Mode::Notify(shutdown_tx_mutex) => { |
| 39 | + let Some(shutdown_tx) = shutdown_tx_mutex.lock().take() else { |
| 40 | + // A shutdown message has already been sent for this instance. Do nothing. |
| 41 | + return; |
| 42 | + }; |
| 43 | + _ = shutdown_tx.send(fatal_error); |
| 44 | + }, |
| 45 | + Mode::Panic => { |
| 46 | + // We don't have the shutdown signal configured. Just panic. |
| 47 | + panic!("Shutting down due to fatal error: {}", fatal_error); |
| 48 | + }, |
51 | 49 | }
|
52 | 50 | }
|
53 | 51 |
|
54 |
| - // Creates a new ShutdownSignal that panics when signaled. |
| 52 | + /// Creates a new ShutdownSignal that panics when signaled. |
55 | 53 | pub fn panic() -> Self {
|
56 |
| - Self { |
57 |
| - shutdown_tx: None, |
58 |
| - instance_name: "".to_owned(), |
59 |
| - generation_id: 0, |
60 |
| - } |
| 54 | + Self { mode: Mode::Panic } |
61 | 55 | }
|
62 | 56 |
|
63 | 57 | #[cfg(any(test, feature = "testing"))]
|
64 | 58 | pub fn no_op() -> Self {
|
65 | 59 | Self {
|
66 |
| - shutdown_tx: Some(Arc::new(Mutex::new(None))), |
67 |
| - instance_name: "".to_owned(), |
68 |
| - generation_id: 0, |
| 60 | + mode: Mode::Notify(Arc::new(Mutex::new(None))), |
69 | 61 | }
|
70 | 62 | }
|
71 | 63 | }
|
0 commit comments