mod allocation;
#[cfg(unix)]
mod data;
#[cfg(unix)]
pub use data::{
IcSnapshotDataUploadExecutionError, IcSnapshotDataUploadReplyError, upload_snapshot_data,
};
pub use allocation::{
IcSnapshotAllocationExecutionError, IcSnapshotAllocationSettlementError, allocate_snapshot,
};
use crate::{
model::{
ic_mutation::IcMutationAcknowledgement,
ic_snapshot_upload::{
IcSnapshotUploadAttempt, IcSnapshotUploadAttemptError, IcSnapshotUploadRequest,
original_authority,
},
operation_plan::OperationPlanError,
},
ops::persistence::{
AttemptJournalError, AttemptJournalGuard, ExecutionProgressPersistenceError,
ExecutionStageGuard, ExecutionWorkflowPersistenceError,
},
policy::ic_snapshot_upload::{
IcSnapshotUploadAcknowledgementView, IcSnapshotUploadAssociationError,
validate_acknowledgement,
},
ports::{ic_mutation::IcMutationProviderError, ic_snapshot_upload::IcSnapshotUploadProvider},
};
use thiserror::Error;
async fn upload_snapshot_with<E: std::error::Error + 'static, T>(
stage: &ExecutionStageGuard<'_>,
operation_sequence: u64,
payload: &IcSnapshotUploadRequest<'_>,
provider: &mut impl IcSnapshotUploadProvider,
admit: impl AsyncFnOnce(&IcSnapshotUploadAttempt<'_, '_>) -> Result<(), E>,
complete: impl AsyncFnOnce(
&mut AttemptJournalGuard<'_>,
&IcSnapshotUploadAttempt<'_, '_>,
&IcSnapshotUploadAcknowledgementView<'_, '_>,
) -> T,
) -> Result<(IcMutationAcknowledgement, T), IcSnapshotUploadExecutionError<E>> {
let plan = stage.plan();
let authority = plan.attempt_authority(operation_sequence)?;
let (acknowledgement, result) = super::ic_mutation::execute_reserved(
stage,
&authority,
|journal| {
original_authority(plan, operation_sequence, journal, payload)?;
Ok::<_, IcSnapshotUploadExecutionError<E>>(())
},
|journal| {
Ok(IcSnapshotUploadAttempt::new(
plan,
operation_sequence,
journal,
payload,
)?)
},
async |request| {
admit(request)
.await
.map_err(IcSnapshotUploadExecutionError::Admission)?;
stage.layout()?;
Ok(())
},
async |request, journal| Ok(provider.submit_upload(request, journal).await?),
async |journal, request, acknowledgement| {
let admitted = validate_acknowledgement(request, journal.record()?, acknowledgement)?;
stage.layout()?;
Ok::<_, IcSnapshotUploadReplyError>(complete(journal, request, &admitted).await)
},
)
.await?;
super::qualified_receipt::retain_reply(acknowledgement, result, |source, acknowledgement| {
IcSnapshotUploadExecutionError::AfterReply {
source,
acknowledgement,
}
})
}
#[derive(Debug, Error)]
pub enum IcSnapshotUploadExecutionError<E: std::error::Error + 'static> {
#[error(transparent)]
Plan(#[from] OperationPlanError),
#[error(transparent)]
Stage(#[from] ExecutionWorkflowPersistenceError),
#[error(transparent)]
Journal(#[from] AttemptJournalError),
#[error(transparent)]
Progress(#[from] ExecutionProgressPersistenceError),
#[error(transparent)]
Request(#[from] IcSnapshotUploadAttemptError),
#[error("fresh snapshot upload admission failed: {0}")]
Admission(#[source] E),
#[error(transparent)]
Provider(#[from] IcMutationProviderError),
#[error("snapshot upload reply rejected: {source}")]
AfterReply {
source: IcSnapshotUploadReplyError,
acknowledgement: Box<IcMutationAcknowledgement>,
},
}
#[derive(Debug, Error)]
pub enum IcSnapshotUploadReplyError {
#[error(transparent)]
Journal(#[from] AttemptJournalError),
#[error(transparent)]
Association(#[from] IcSnapshotUploadAssociationError),
#[error(transparent)]
Stage(#[from] ExecutionWorkflowPersistenceError),
}
#[cfg(all(test, unix))]
mod tests;