Skip to main content

coven_replication/sync/store/circles/
error.rs

1use crate::sync::store::{StoreError, StoreRegistrationError};
2use coven_protocol::circle::{CircleId, CircleTransitionError};
3use coven_protocol::objects::StoreObjectError;
4
5#[derive(Debug, thiserror::Error)]
6pub enum CircleOperationError {
7    #[error("database: {0}")]
8    Database(coven_database::DbError),
9    #[error("circle protocol state is absent: {0}")]
10    MissingState(&'static str),
11    #[error("circle protocol state is invalid: {0}")]
12    InvalidState(String),
13    #[error("circle state reduction: {0}")]
14    State(#[from] coven_protocol::circle_activation::CircleStateError),
15    #[error("circle row blob reference: {0}")]
16    RowBlob(#[from] coven_protocol::blob::RowBlobRefError),
17    #[error("circle construction: {0}")]
18    Construction(#[from] CircleTransitionError),
19    #[error("Circle epoch-close response: {0}")]
20    EpochCloseResponse(#[source] CircleTransitionError),
21    #[error("circle protocol: {0}")]
22    Protocol(#[from] coven_protocol::store_commit::StoreProtocolError),
23    #[error("circle roster: {0}")]
24    Roster(#[from] coven_protocol::circle_roster::CircleRosterError),
25    #[error("circle row routing key: {0}")]
26    RowRoutingKey(#[from] coven_protocol::circle::RowRoutingKeyError),
27    #[error("circle snapshot image: {0}")]
28    SnapshotImage(#[from] coven_database::SnapshotImageError),
29    #[error("circle encryption: {0}")]
30    Encryption(#[from] coven_keys::encryption::EncryptionError),
31    #[error("circle key operation: {0}")]
32    Key(#[from] coven_keys::keys::KeyError),
33    #[error("circle JSON: {0}")]
34    Json(#[from] serde_json::Error),
35    #[error("circle storage: {0}")]
36    Storage(#[from] coven_protocol::objects::StorageError),
37    #[error("circle object: {0}")]
38    Object(#[from] StoreObjectError),
39    #[error("circle blob download: {0}")]
40    BlobDownload(#[from] crate::sync::store::blob::BlobDownloadFailureCause),
41    #[error("Store publication: {0}")]
42    StoreOutbound(#[from] StoreError),
43    #[error("Store device registration: {0}")]
44    StoreRegistration(#[from] StoreRegistrationError),
45    #[error("circle writer authorization: {0}")]
46    WriterAuthorization(#[source] Box<crate::sync::store::StoreWriterAuthorizationError>),
47    #[error("circle sync cycle: {0}")]
48    SyncCycle(#[source] Box<crate::sync::cycle::SyncCycleFailure>),
49    #[error("circle Store pull: {0}")]
50    StorePull(#[source] Box<crate::sync::store::StorePullError>),
51    #[error("circle membership chain: {0}")]
52    AnchoredChain(#[source] Box<crate::sync::store::AnchoredChainError>),
53    #[error("circles require opaque cloud storage")]
54    BrowsableStorage,
55    #[error("circle operation journal: {0}")]
56    Journal(#[from] coven_protocol::circle_journal::CircleJournalError),
57    #[error("circle operation journal state: {0}")]
58    JournalState(String),
59    #[error("circle operation {circle_id} is blocked: {block}")]
60    Blocked {
61        circle_id: CircleId,
62        block: coven_protocol::circle::CircleOperationBlock,
63    },
64    #[error("circle {circle_id} requires rotation: its roster names removed Store members {removed_members:?}")]
65    RotationRequired {
66        circle_id: CircleId,
67        removed_members: Vec<String>,
68    },
69    #[error("device excluded from circle {circle_id} close {close_id} must reset from the successor bootstrap before publishing")]
70    ExcludedDeviceMustReset {
71        circle_id: CircleId,
72        close_id: coven_protocol::circle::CircleEpochCloseId,
73    },
74    #[error("circle {circle_id} has no retained control conflict to resolve")]
75    NotConflicted { circle_id: CircleId },
76    #[error("circle {circle_id} control conflict does not retain the chosen branch")]
77    ChosenBranchNotRetained { circle_id: CircleId },
78    #[error("circle {circle_id} control conflict cannot be resolved to its closing branch: an epoch close binds its participant responses to the closing control, so a resolution successor under a new control coordinate would strand them; resolve to a non-closing branch to discard the close instead")]
79    ResolveToClosingBranch { circle_id: CircleId },
80    #[error("circle {circle_id} has no local epoch close waiting for cancellation")]
81    NoCloseToCancel { circle_id: CircleId },
82    #[error("circle {circle_id} has no local epoch close waiting for device exclusion")]
83    NoCloseToExclude { circle_id: CircleId },
84    #[error("device {device_id} is not a participant in circle {circle_id}'s epoch close")]
85    DeviceNotACloseParticipant {
86        circle_id: CircleId,
87        device_id: coven_protocol::store_commit::StoreDeviceId,
88    },
89    #[error("circle operation {operation_id} is not blocked")]
90    NotBlocked {
91        operation_id: coven_protocol::circle::CircleOperationId,
92    },
93    #[error("circle operation {operation_id} discard requires verified permanent nonactivation; it never assumes an unseen candidate failed to activate")]
94    DiscardRequiresNonactivation {
95        operation_id: coven_protocol::circle::CircleOperationId,
96    },
97    #[error("circle {circle_id} has an unresolved control conflict")]
98    Conflicted { circle_id: CircleId },
99    #[error("circle {circle_id} is deleted")]
100    Deleted { circle_id: CircleId },
101    #[error("circle command channel is closed")]
102    CommandChannelClosed,
103    #[error("circle command ended without a reply")]
104    ReplyChannelClosed,
105}
106
107impl From<coven_database::DbError> for CircleOperationError {
108    fn from(error: coven_database::DbError) -> Self {
109        match error {
110            coven_database::DbError::ExcludedDeviceMustReset {
111                circle_id,
112                close_id,
113            } => Self::ExcludedDeviceMustReset {
114                circle_id,
115                close_id,
116            },
117            other => Self::Database(other),
118        }
119    }
120}
121
122impl From<crate::sync::store::StoreWriterAuthorizationError> for CircleOperationError {
123    fn from(error: crate::sync::store::StoreWriterAuthorizationError) -> Self {
124        Self::WriterAuthorization(Box::new(error))
125    }
126}
127
128impl From<crate::sync::cycle::SyncCycleFailure> for CircleOperationError {
129    fn from(error: crate::sync::cycle::SyncCycleFailure) -> Self {
130        Self::SyncCycle(Box::new(error))
131    }
132}
133
134impl From<crate::sync::store::StorePullError> for CircleOperationError {
135    fn from(error: crate::sync::store::StorePullError) -> Self {
136        Self::StorePull(Box::new(error))
137    }
138}
139
140impl From<crate::sync::store::AnchoredChainError> for CircleOperationError {
141    fn from(error: crate::sync::store::AnchoredChainError) -> Self {
142        Self::AnchoredChain(Box::new(error))
143    }
144}