ic_backup/workflow/ic_snapshot_transfer_read/
mod.rs1use crate::{
4 model::{
5 ic_snapshot_transfer_read::{
6 IcSnapshotTransferReadError, IcSnapshotTransferReadPayload,
7 IcSnapshotTransferReadRequest, IcSnapshotTransferReadResponse,
8 },
9 operation_plan::OperationPlanError,
10 },
11 ops::persistence::{
12 AttemptJournalError, AttemptJournalGuard, ExecutionProgressPersistenceError,
13 ExecutionStageGuard, ExecutionWorkflowPersistenceError,
14 },
15 policy::ic_snapshot_transfer_read::{
16 IcSnapshotTransferReadAssociationError, IcSnapshotTransferReadView, validate_response,
17 },
18 ports::{
19 ic_observation::IcObservationProviderError,
20 ic_snapshot_transfer_read::IcSnapshotTransferReadProvider,
21 },
22};
23use thiserror::Error;
24
25pub(super) async fn read_snapshot_with<E: std::error::Error + 'static, T>(
29 stage: &ExecutionStageGuard<'_>,
30 operation_sequence: u64,
31 payload: IcSnapshotTransferReadPayload<'_, '_>,
32 provider: &mut impl IcSnapshotTransferReadProvider,
33 admit: impl AsyncFnOnce(&IcSnapshotTransferReadRequest<'_, '_>) -> Result<(), E>,
34 complete: impl AsyncFnOnce(
35 &mut AttemptJournalGuard<'_>,
36 &IcSnapshotTransferReadRequest<'_, '_>,
37 &IcSnapshotTransferReadView<'_, '_>,
38 ) -> T,
39) -> Result<(IcSnapshotTransferReadResponse, T), IcSnapshotTransferReadExecutionError<E>> {
40 let plan = stage.plan();
41 let authority = plan.attempt_authority(operation_sequence)?;
42 payload.validate_binding(&authority)?;
43 let (response, result) = super::ic_mutation::execute_reserved(
44 stage,
45 &authority,
46 |_| Ok::<_, IcSnapshotTransferReadExecutionError<E>>(()),
47 |journal| {
48 Ok(IcSnapshotTransferReadRequest::new(
49 plan,
50 operation_sequence,
51 journal,
52 payload,
53 )?)
54 },
55 async |request| {
56 admit(request)
57 .await
58 .map_err(IcSnapshotTransferReadExecutionError::Admission)?;
59 stage.layout()?;
60 Ok(())
61 },
62 async |request, journal| Ok(provider.read_snapshot(request, journal).await?),
63 async |journal, request, response| {
64 let admitted = validate_response(request, journal.record()?, response)?;
65 stage.layout()?;
66 Ok::<_, IcSnapshotTransferReadReplyError>(complete(journal, request, &admitted).await)
67 },
68 )
69 .await?;
70 super::qualified_receipt::retain_reply(response, result, |source, response| {
71 IcSnapshotTransferReadExecutionError::AfterReply { source, response }
72 })
73}
74
75#[derive(Debug, Error)]
77pub enum IcSnapshotTransferReadExecutionError<E: std::error::Error + 'static> {
78 #[error(transparent)]
80 Plan(#[from] OperationPlanError),
81 #[error(transparent)]
83 Stage(#[from] ExecutionWorkflowPersistenceError),
84 #[error(transparent)]
86 Journal(#[from] AttemptJournalError),
87 #[error(transparent)]
89 Progress(#[from] ExecutionProgressPersistenceError),
90 #[error(transparent)]
92 Request(#[from] IcSnapshotTransferReadError),
93 #[error("fresh snapshot read admission failed: {0}")]
95 Admission(#[source] E),
96 #[error(transparent)]
98 Provider(#[from] IcObservationProviderError),
99 #[error("snapshot transfer read reply rejected: {source}")]
101 AfterReply {
102 source: IcSnapshotTransferReadReplyError,
104 response: Box<IcSnapshotTransferReadResponse>,
106 },
107}
108
109#[derive(Debug, Error)]
111pub enum IcSnapshotTransferReadReplyError {
112 #[error(transparent)]
114 Journal(#[from] AttemptJournalError),
115 #[error(transparent)]
117 Association(#[from] IcSnapshotTransferReadAssociationError),
118 #[error(transparent)]
120 Stage(#[from] ExecutionWorkflowPersistenceError),
121}
122
123#[cfg(all(test, unix))]
124mod tests;