use super::{AttemptJournalError, BackupLayoutGuard, OperationPlanPersistenceError};
use crate::{
model::{
artifacts::ArtifactChecksumRecord, attempt_journal::AttemptJournalRecord,
operation_plan::OperationPlanError,
},
policy::execution_progress::{ExecutionProgressError, ExecutionProgressView, admit_progress},
};
use thiserror::Error;
pub fn read_execution_progress(
layout: &BackupLayoutGuard,
expected_plan: &ArtifactChecksumRecord,
) -> Result<ExecutionProgressView, ExecutionProgressPersistenceError> {
let (plan, journals) = super::attempt_journal::read_original_plan_journals::<
ExecutionProgressPersistenceError,
>(layout, expected_plan, None)?;
Ok(admit_progress(&plan, journals.iter())?.project()?)
}
pub(super) fn admit_with_current(
layout: &BackupLayoutGuard,
expected_plan: &ArtifactChecksumRecord,
current: &AttemptJournalRecord,
require_dependencies: bool,
) -> Result<(), ExecutionProgressPersistenceError> {
let (plan, journals) = super::attempt_journal::read_original_plan_journals::<
ExecutionProgressPersistenceError,
>(layout, expected_plan, Some(current))?;
let admitted = admit_progress(&plan, journals.iter())?;
let sequence = current.authority().binding().operation_sequence();
if require_dependencies
&& !admitted.dependencies_applied(plan.operation(sequence)?.depends_on())
{
return Err(ExecutionProgressPersistenceError::DependenciesUnapplied(
sequence,
));
}
Ok(())
}
#[derive(Debug, Error)]
pub enum ExecutionProgressPersistenceError {
#[error(transparent)]
Plan(#[from] OperationPlanPersistenceError),
#[error(transparent)]
Authority(#[from] OperationPlanError),
#[error(transparent)]
Journal(#[from] AttemptJournalError),
#[error(transparent)]
Policy(#[from] ExecutionProgressError),
#[error("operation {0} has unapplied prerequisites")]
DependenciesUnapplied(u64),
}
#[cfg(all(test, unix))]
mod tests;