coven_replication/sync/cycle/
failure.rs1#[derive(Debug)]
2pub struct SyncCycleFailure {
3 kind: SyncCycleFailureKind,
4 operation: &'static str,
5 cause: Box<SyncCycleCause>,
6}
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9enum SyncCycleFailureKind {
10 Offline,
11 Failed,
12}
13
14impl SyncCycleFailure {
15 pub(crate) fn operation<E>(operation: &'static str, error: E) -> Self
16 where
17 E: Into<SyncCycleCause>,
18 {
19 let cause = error.into();
20 let kind = if crate::sync::error::error_chain_contains_transport(&cause) {
21 SyncCycleFailureKind::Offline
22 } else {
23 SyncCycleFailureKind::Failed
24 };
25 Self {
26 kind,
27 operation,
28 cause: Box::new(cause),
29 }
30 }
31
32 pub(crate) fn is_offline(&self) -> bool {
33 self.kind == SyncCycleFailureKind::Offline
34 }
35
36 pub(super) fn concurrent(first: Self, second: Self) -> Self {
37 let kind = if first.is_offline() || second.is_offline() {
38 SyncCycleFailureKind::Offline
39 } else {
40 SyncCycleFailureKind::Failed
41 };
42 Self {
43 kind,
44 operation: "run Store publication and blob upload lanes",
45 cause: Box::new(SyncCycleCause::Concurrent {
46 first: Box::new(first),
47 second: Box::new(second),
48 }),
49 }
50 }
51
52 #[cfg(test)]
53 pub(crate) fn contains(&self, pattern: &str) -> bool {
54 self.to_string().contains(pattern)
55 }
56}
57
58impl std::fmt::Display for SyncCycleFailure {
59 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
60 write!(formatter, "{}: {}", self.operation, self.cause)
61 }
62}
63
64impl std::error::Error for SyncCycleFailure {
65 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
66 Some(self.cause.as_ref())
67 }
68}
69
70#[derive(Debug, thiserror::Error)]
71pub(crate) enum SyncCycleCause {
72 #[error("{first}; concurrently, {second}")]
73 Concurrent {
74 first: Box<SyncCycleFailure>,
75 second: Box<SyncCycleFailure>,
76 },
77 #[error("{0}")]
78 Database(#[from] coven_database::DbError),
79 #[error("{0}")]
80 Store(#[from] crate::sync::store::StoreError),
81 #[error("{0}")]
82 Registration(#[from] crate::sync::store::StoreRegistrationError),
83 #[error("{0}")]
84 Initialization(#[from] crate::sync::store::StoreInitializationError),
85 #[error("{0}")]
86 Circle(#[from] crate::sync::store::CircleOperationError),
87 #[error("{0}")]
88 DeviceExclusion(#[from] crate::sync::store::StoreDeviceExclusionError),
89 #[error("{0}")]
90 Reclaim(#[from] crate::sync::store::StoreReclaimError),
91 #[error("{0}")]
92 DeviceJoin(#[from] crate::sync::store::DeviceJoinError),
93 #[error("{0}")]
94 TombstoneDrain(#[from] crate::blob::delete::TombstoneDrainError),
95 #[error("{0}")]
96 TombstoneGc(#[from] crate::sync::store::commit_publication::operation::TombstoneGcError),
97 #[error("{0}")]
98 UploadFailures(#[from] crate::blob::UploadFailures),
99 #[error("{0}")]
100 WriterAuthorization(
101 #[from] crate::sync::store::commit_publication::operation::StoreWriterAuthorizationError,
102 ),
103 #[error("{0}")]
104 Acknowledgement(#[from] crate::sync::store::acknowledgements::StoreAckError),
105 #[error("{0}")]
106 Membership(#[from] crate::sync::store::MembershipOpsError),
107 #[error("{0}")]
108 Pull(#[from] crate::sync::store::StorePullError),
109 #[error("{0}")]
110 AuthorizationRefresh(
111 #[from] crate::sync::store::commit_publication::operation::AuthorizationRefreshError,
112 ),
113 #[error("{0}")]
114 PublishedBlobDrop(#[from] crate::sync::store::blob::PublishedBlobDropError),
115 #[error("{0}")]
116 StoreProtocol(#[from] coven_protocol::store_commit::StoreProtocolError),
117 #[error("{0}")]
118 RowRoutingKey(#[from] coven_protocol::circle::RowRoutingKeyError),
119 #[error("{0}")]
120 Snapshot(#[from] crate::sync::store::snapshots::SnapshotError),
121}
122
123#[cfg(test)]
124#[path = "failure_tests.rs"]
125mod tests;