Skip to main content

ic_backup/ops/persistence/execution_progress/
mod.rs

1//! Original retained plan/journal admission for local progress and guarded reservations.
2
3use super::{AttemptJournalError, BackupLayoutGuard, OperationPlanPersistenceError};
4use crate::{
5    model::{
6        artifacts::ArtifactChecksumRecord, attempt_journal::AttemptJournalRecord,
7        operation_plan::OperationPlanError,
8    },
9    policy::execution_progress::{
10        ExecutionProgressError, ExecutionProgressRequest, ExecutionProgressView, progress,
11    },
12};
13use thiserror::Error;
14
15/// Read complete original retained execution evidence without remote effects or artifact reads.
16///
17/// Requires the exact persisted plan and every original attempt journal. Missing
18/// journals never supply zero consumption. Journal locks are taken sequentially;
19/// hold no attempt guards when calling this function. The layout retains cooperating
20/// exclusion, while noncooperating byte custody remains integration-owned.
21/// This grants no fresh permission, executable call, authenticated receipt or release.
22/// # Errors
23/// Rejects missing/unsafe/changed originals, contention and invalid retained causality.
24pub fn read_execution_progress(
25    layout: &BackupLayoutGuard,
26    expected_plan: &ArtifactChecksumRecord,
27) -> Result<ExecutionProgressView, ExecutionProgressPersistenceError> {
28    read_with_current(layout, expected_plan, None)
29}
30
31pub(super) fn read_with_current(
32    layout: &BackupLayoutGuard,
33    expected_plan: &ArtifactChecksumRecord,
34    current: Option<&AttemptJournalRecord>,
35) -> Result<ExecutionProgressView, ExecutionProgressPersistenceError> {
36    let (plan, journals) = super::attempt_journal::read_original_plan_journals::<
37        ExecutionProgressPersistenceError,
38    >(layout, expected_plan, current)?;
39    let references: Vec<_> = journals.iter().collect();
40    Ok(progress(&ExecutionProgressRequest {
41        plan: &plan,
42        journals: &references,
43    })?)
44}
45
46/// Typed local evidence or reservation rejection; no failure resets original spending.
47#[derive(Debug, Error)]
48pub enum ExecutionProgressPersistenceError {
49    /// Exact original persisted plan cannot be admitted.
50    #[error(transparent)]
51    Plan(#[from] OperationPlanPersistenceError),
52    /// Original bulk authority derivation failed.
53    #[error(transparent)]
54    Authority(#[from] OperationPlanError),
55    /// Original journal admission or durable reservation failed.
56    #[error(transparent)]
57    Journal(#[from] AttemptJournalError),
58    /// Complete retained accounting/causality cannot be projected.
59    #[error(transparent)]
60    Policy(#[from] ExecutionProgressError),
61    /// The selected operation has a prerequisite without retained Applied evidence.
62    #[error("operation {0} has unapplied prerequisites")]
63    DependenciesUnapplied(u64),
64}
65
66#[cfg(all(test, unix))]
67mod tests;