ic_backup/workflow/ic_snapshot_upload/
mod.rs1mod allocation;
4#[cfg(unix)]
5mod data;
6#[cfg(unix)]
7pub use data::{
8 IcSnapshotDataUploadExecutionError, IcSnapshotDataUploadReplyError, upload_snapshot_data,
9};
10
11pub use allocation::{
12 IcSnapshotAllocationExecutionError, IcSnapshotAllocationSettlementError, allocate_snapshot,
13};
14
15use crate::{
16 model::{
17 ic_mutation::IcMutationAcknowledgement,
18 ic_snapshot_upload::{
19 IcSnapshotUploadAttempt, IcSnapshotUploadAttemptError, IcSnapshotUploadRequest,
20 original_authority,
21 },
22 operation_plan::OperationPlanError,
23 },
24 ops::persistence::{
25 AttemptJournalError, AttemptJournalGuard, ExecutionProgressPersistenceError,
26 ExecutionStageGuard, ExecutionWorkflowPersistenceError,
27 },
28 policy::ic_snapshot_upload::{
29 IcSnapshotUploadAcknowledgementView, IcSnapshotUploadAssociationError,
30 validate_acknowledgement,
31 },
32 ports::{ic_mutation::IcMutationProviderError, ic_snapshot_upload::IcSnapshotUploadProvider},
33};
34use thiserror::Error;
35
36pub async fn upload_snapshot<E: std::error::Error + 'static>(
68 stage: &ExecutionStageGuard<'_>,
69 operation_sequence: u64,
70 payload: &IcSnapshotUploadRequest<'_>,
71 provider: &mut impl IcSnapshotUploadProvider,
72 admit: impl AsyncFnOnce(&IcSnapshotUploadAttempt<'_, '_>) -> Result<(), E>,
73) -> Result<IcMutationAcknowledgement, IcSnapshotUploadExecutionError<E>> {
74 let (acknowledgement, ()) = upload_snapshot_with(
75 stage,
76 operation_sequence,
77 payload,
78 provider,
79 admit,
80 async |_, _, _| (),
81 )
82 .await?;
83 Ok(acknowledgement)
84}
85
86async fn upload_snapshot_with<E: std::error::Error + 'static, T>(
89 stage: &ExecutionStageGuard<'_>,
90 operation_sequence: u64,
91 payload: &IcSnapshotUploadRequest<'_>,
92 provider: &mut impl IcSnapshotUploadProvider,
93 admit: impl AsyncFnOnce(&IcSnapshotUploadAttempt<'_, '_>) -> Result<(), E>,
94 complete: impl AsyncFnOnce(
95 &mut AttemptJournalGuard<'_>,
96 &IcSnapshotUploadAttempt<'_, '_>,
97 &IcSnapshotUploadAcknowledgementView<'_, '_>,
98 ) -> T,
99) -> Result<(IcMutationAcknowledgement, T), IcSnapshotUploadExecutionError<E>> {
100 let plan = stage.plan();
101 let authority = plan.attempt_authority(operation_sequence)?;
102 let mut journal = AttemptJournalGuard::open(stage.layout()?, &authority)?;
103 original_authority(plan, operation_sequence, journal.record()?, payload)?;
104 journal.reserve_planned_mutation(&plan.digest())?;
105 let request =
106 IcSnapshotUploadAttempt::new(plan, operation_sequence, journal.record()?, payload)?;
107 admit(&request)
108 .await
109 .map_err(IcSnapshotUploadExecutionError::Admission)?;
110 stage.layout()?;
111 let acknowledgement = provider.submit_upload(&request, journal.record()?).await?;
112 let admit_reply = || {
113 let admitted = validate_acknowledgement(&request, journal.record()?, &acknowledgement)?;
114 stage.layout()?;
115 Ok::<_, IcSnapshotUploadReplyError>(admitted)
116 };
117 let admitted = match admit_reply() {
118 Ok(admitted) => admitted,
119 Err(source) => {
120 return Err(IcSnapshotUploadExecutionError::AfterReply {
121 source,
122 acknowledgement: Box::new(acknowledgement),
123 });
124 }
125 };
126 let result = complete(&mut journal, &request, &admitted).await;
127 Ok((acknowledgement, result))
128}
129
130#[derive(Debug, Error)]
132pub enum IcSnapshotUploadExecutionError<E: std::error::Error + 'static> {
133 #[error(transparent)]
135 Plan(#[from] OperationPlanError),
136 #[error(transparent)]
138 Stage(#[from] ExecutionWorkflowPersistenceError),
139 #[error(transparent)]
141 Journal(#[from] AttemptJournalError),
142 #[error(transparent)]
144 Progress(#[from] ExecutionProgressPersistenceError),
145 #[error(transparent)]
147 Request(#[from] IcSnapshotUploadAttemptError),
148 #[error("fresh snapshot upload admission failed: {0}")]
150 Admission(#[source] E),
151 #[error(transparent)]
153 Provider(#[from] IcMutationProviderError),
154 #[error("snapshot upload reply rejected: {source}")]
156 AfterReply {
157 source: IcSnapshotUploadReplyError,
159 acknowledgement: Box<IcMutationAcknowledgement>,
161 },
162}
163
164#[derive(Debug, Error)]
166pub enum IcSnapshotUploadReplyError {
167 #[error(transparent)]
169 Journal(#[from] AttemptJournalError),
170 #[error(transparent)]
172 Association(#[from] IcSnapshotUploadAssociationError),
173 #[error(transparent)]
175 Stage(#[from] ExecutionWorkflowPersistenceError),
176}
177
178#[cfg(all(test, unix))]
179mod tests;