-
Notifications
You must be signed in to change notification settings - Fork 109
Expand file tree
/
Copy pathsuspend.rs
More file actions
113 lines (98 loc) · 3.59 KB
/
suspend.rs
File metadata and controls
113 lines (98 loc) · 3.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use std::fmt::Display;
use serde::{Deserialize, Serialize};
use thiserror::Error as ThisError;
use utoipa::ToSchema;
/// Whether a pipeline supports checkpointing and suspend-and-resume.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
pub enum SuspendError {
/// Pipeline does not support suspend-and-resume.
///
/// These reasons only change if the pipeline's configuration changes, e.g.
/// if a pipeline has an input connector that does not support
/// suspend-and-resume, and then that input connector is removed.
Permanent(
/// Reasons why the pipeline does not support suspend-and-resume.
Vec<PermanentSuspendError>,
),
/// Pipeline supports suspend-and-resume, but a suspend requested now will
/// be delayed.
Temporary(
/// Reasons that the suspend will be delayed.
Vec<TemporarySuspendError>,
),
}
impl Display for SuspendError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SuspendError::Permanent(reasons) => {
write!(
f,
"The pipeline does not support checkpointing for the following reasons:"
)?;
for (index, reason) in reasons.iter().enumerate() {
if index > 0 {
write!(f, ",")?;
}
write!(f, " {reason}")?;
}
}
SuspendError::Temporary(delays) => {
write!(
f,
"Checkpointing the pipeline will be temporarily delayed for the following reasons:"
)?;
for (index, delay) in delays.iter().enumerate() {
if index > 0 {
write!(f, ",")?;
}
write!(f, " {delay}")?;
}
}
}
Ok(())
}
}
/// Reasons why a pipeline does not support suspend and resume operations.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, ThisError, ToSchema)]
pub enum PermanentSuspendError {
#[error("Storage must be configured")]
StorageRequired,
#[error("Suspend is an enterprise feature")]
EnterpriseFeature,
#[error("Input endpoint {0:?} does not support suspend")]
UnsupportedInputEndpoint(String),
}
/// Reasons why a pipeline cannot be suspended at this time.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, ThisError, ToSchema)]
pub enum TemporarySuspendError {
#[error("The pipeline is replaying the journal")]
Replaying,
#[error("The pipeline is bootstrapping")]
Bootstrapping,
#[error("The pipeline is processing a transaction")]
TransactionInProgress,
#[error("Input endpoint {0:?} is blocking suspend")]
InputEndpointBarrier(String),
#[error("Coordinator is blocking checkpoint")]
Coordination,
}
/// Response to a `/suspendable` request.
///
/// Reports whether the pipeline supports suspend and resume operations.
/// If not, provides the reasons why suspending is not supported.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, ToSchema)]
pub struct SuspendableResponse {
/// Is the pipeline suspendable?
pub suspendable: bool,
/// If the pipeline is not suspendable, why not?
pub reasons: Vec<PermanentSuspendError>,
}
impl SuspendableResponse {
/// Create a new suspendable response.
pub fn new(suspendable: bool, reasons: Vec<PermanentSuspendError>) -> Self {
Self {
suspendable,
reasons,
}
}
}