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
36async fn upload_snapshot_with<E: std::error::Error + 'static, T>(
39 stage: &ExecutionStageGuard<'_>,
40 operation_sequence: u64,
41 payload: &IcSnapshotUploadRequest<'_>,
42 provider: &mut impl IcSnapshotUploadProvider,
43 admit: impl AsyncFnOnce(&IcSnapshotUploadAttempt<'_, '_>) -> Result<(), E>,
44 complete: impl AsyncFnOnce(
45 &mut AttemptJournalGuard<'_>,
46 &IcSnapshotUploadAttempt<'_, '_>,
47 &IcSnapshotUploadAcknowledgementView<'_, '_>,
48 ) -> T,
49) -> Result<(IcMutationAcknowledgement, T), IcSnapshotUploadExecutionError<E>> {
50 let plan = stage.plan();
51 let authority = plan.attempt_authority(operation_sequence)?;
52 let (acknowledgement, result) = super::ic_mutation::execute_reserved(
53 stage,
54 &authority,
55 |journal| {
56 original_authority(plan, operation_sequence, journal, payload)?;
57 Ok::<_, IcSnapshotUploadExecutionError<E>>(())
58 },
59 |journal| {
60 Ok(IcSnapshotUploadAttempt::new(
61 plan,
62 operation_sequence,
63 journal,
64 payload,
65 )?)
66 },
67 async |request| {
68 admit(request)
69 .await
70 .map_err(IcSnapshotUploadExecutionError::Admission)?;
71 stage.layout()?;
72 Ok(())
73 },
74 async |request, journal| Ok(provider.submit_upload(request, journal).await?),
75 async |journal, request, acknowledgement| {
76 let admitted = validate_acknowledgement(request, journal.record()?, acknowledgement)?;
77 stage.layout()?;
78 Ok::<_, IcSnapshotUploadReplyError>(complete(journal, request, &admitted).await)
79 },
80 )
81 .await?;
82 super::qualified_receipt::retain_reply(acknowledgement, result, |source, acknowledgement| {
83 IcSnapshotUploadExecutionError::AfterReply {
84 source,
85 acknowledgement,
86 }
87 })
88}
89
90#[derive(Debug, Error)]
92pub enum IcSnapshotUploadExecutionError<E: std::error::Error + 'static> {
93 #[error(transparent)]
95 Plan(#[from] OperationPlanError),
96 #[error(transparent)]
98 Stage(#[from] ExecutionWorkflowPersistenceError),
99 #[error(transparent)]
101 Journal(#[from] AttemptJournalError),
102 #[error(transparent)]
104 Progress(#[from] ExecutionProgressPersistenceError),
105 #[error(transparent)]
107 Request(#[from] IcSnapshotUploadAttemptError),
108 #[error("fresh snapshot upload admission failed: {0}")]
110 Admission(#[source] E),
111 #[error(transparent)]
113 Provider(#[from] IcMutationProviderError),
114 #[error("snapshot upload reply rejected: {source}")]
116 AfterReply {
117 source: IcSnapshotUploadReplyError,
119 acknowledgement: Box<IcMutationAcknowledgement>,
121 },
122}
123
124#[derive(Debug, Error)]
126pub enum IcSnapshotUploadReplyError {
127 #[error(transparent)]
129 Journal(#[from] AttemptJournalError),
130 #[error(transparent)]
132 Association(#[from] IcSnapshotUploadAssociationError),
133 #[error(transparent)]
135 Stage(#[from] ExecutionWorkflowPersistenceError),
136}
137
138#[cfg(all(test, unix))]
139mod tests;