Skip to main content

ic_backup/ops/persistence/
mod.rs

1//! Durable publication, journal/layout exclusion and retained local dependencies.
2
3mod artifact_commit;
4mod attempt_journal;
5mod command_lifetime_lock;
6mod consistency;
7mod download_journal;
8mod effect_graph;
9mod execution_progress;
10mod execution_settlement;
11mod execution_workflow;
12mod fence_obligation;
13mod file_lock;
14mod inventory;
15mod journal_lock;
16mod json;
17mod layout_lifetime;
18mod operation_plan;
19mod restore_safety;
20
21pub use artifact_commit::{ArtifactCommitOutcome, commit_artifact_directory};
22pub use attempt_journal::{AttemptJournalError, AttemptJournalGuard};
23pub use command_lifetime_lock::{
24    COMMAND_CUSTODY_DESCRIPTOR_ENV, CommandLifetimeLock, CommandLifetimeLockError,
25    CommandQuiescenceGuard,
26};
27pub use consistency::{
28    ConsistencyPersistenceError, create_consistency_requirement, read_consistency_requirement,
29};
30pub use download_journal::{
31    DownloadIntegrityError, DownloadJournalError, DownloadJournalGuard, DownloadManifestError,
32    LocalRestoreArtifactError, LocalRestoreArtifactPublicationError, LocalRestoreArtifactView,
33    LocalRestoreSourceError, read_download_manifest,
34};
35#[cfg(unix)]
36pub use download_journal::{
37    IcSnapshotArtifactError, IcSnapshotArtifactWriter, IcSnapshotLocalMetrics,
38    IcSnapshotUploadArtifactError, MeasurementHistogram, MeasurementSummary,
39};
40pub use effect_graph::{EffectGraphPersistenceError, create_effect_graph, read_effect_graph};
41pub use execution_progress::{ExecutionProgressPersistenceError, read_execution_progress};
42pub use execution_settlement::{
43    ExecutionSettlementCheckpointError, ExecutionSettlementPersistenceError,
44    checkpoint_execution_settlement, create_execution_settlement, read_execution_settlement,
45};
46pub use execution_workflow::{
47    ExecutionStageCheckpointError, ExecutionStageGuard, ExecutionStagePreparationError,
48    ExecutionStageResumeError, ExecutionWorkflowPersistenceError, create_execution_workflow,
49    read_execution_workflow,
50};
51pub use fence_obligation::{
52    FenceObligationPersistenceError, FenceObligationRequirement, create_fence_obligation,
53    read_fence_obligation,
54};
55pub use inventory::{InventoryError, create_inventory, read_inventory};
56pub use journal_lock::{JournalLock, JournalLockError};
57pub use json::{create_json_durable, read_json, write_json_durable};
58pub use layout_lifetime::{BackupLayoutGuard, MAX_RESTORE_REFERENCE_BYTES};
59pub use operation_plan::{
60    OperationPlanPersistenceError, create_operation_plan, read_operation_plan,
61};
62pub use restore_safety::{
63    RestoreSafetyPersistenceError, create_restore_safety_requirement,
64    read_restore_safety_requirement,
65};
66
67use crate::{model::artifacts::ChecksumError, ops::artifacts::ArtifactError};
68use std::io;
69use thiserror::Error;
70
71/// Typed local persistence failure.
72#[derive(Debug, Error)]
73pub enum PersistenceError {
74    /// An existing layout path no longer denotes the held directory.
75    #[error("backup layout changed while held: {path:?}")]
76    LayoutChanged {
77        /// Resolved layout location.
78        path: std::path::PathBuf,
79    },
80    /// A retained dependency document or journal location has an unsafe entry type.
81    #[error("unsafe restore reference entry: {path:?}")]
82    InvalidRestoreReferences {
83        /// Rejected local path.
84        path: std::path::PathBuf,
85    },
86    /// Restore dependency validation or an immutable retention transition failed.
87    #[error(transparent)]
88    RestoreReference(#[from] crate::model::restore_references::RestoreReferenceError),
89    /// Parent preparation, record reads or other local filesystem IO failed.
90    /// Shared JSON publication failures retain their separate structured boundary.
91    #[error(transparent)]
92    Io(#[from] io::Error),
93    /// Shared file publication failed, retaining producer/cleanup causes and visibility.
94    /// An after-publication failure leaves output visible and requires reconciliation.
95    #[error(transparent)]
96    Publication(#[from] ic_host_fs::durable::NamedWriteError<io::Error>),
97    /// JSON encoding or decoding failed.
98    #[error(transparent)]
99    Json(#[from] serde_json::Error),
100    /// A machine record exceeds its caller-selected byte bound.
101    #[error("record exceeds byte limit {limit}")]
102    RecordTooLarge {
103        /// Maximum accepted bytes.
104        limit: u64,
105    },
106    /// Artifact traversal or streaming failed.
107    #[error(transparent)]
108    Artifact(#[from] ArtifactError),
109    /// Verified bytes do not match the expected checksum.
110    #[error(transparent)]
111    Checksum(#[from] ChecksumError),
112    /// Publication requires distinct siblings in one directory.
113    #[error("artifact commit paths must be distinct siblings: {temporary}, {canonical}")]
114    ArtifactCommitPathMismatch {
115        /// Retained staging path.
116        temporary: String,
117        /// Canonical destination.
118        canonical: String,
119    },
120    /// Both staging and canonical trees exist; neither is overwritten.
121    #[error("artifact commit has conflicting paths: {temporary}, {canonical}")]
122    ArtifactCommitPathConflict {
123        /// Retained staging path.
124        temporary: String,
125        /// Existing canonical destination.
126        canonical: String,
127    },
128    /// Neither expected tree exists.
129    #[error("artifact commit is missing both paths: {temporary}, {canonical}")]
130    ArtifactCommitPathMissing {
131        /// Missing staging path.
132        temporary: String,
133        /// Missing canonical destination.
134        canonical: String,
135    },
136    /// Atomic no-replace directory publication is unsupported.
137    #[error("durable artifact publication is unsupported on {platform}")]
138    ArtifactCommitUnsupportedPlatform {
139        /// Host platform name.
140        platform: &'static str,
141    },
142    /// Publication found an unsafe tree entry.
143    #[error("unsupported artifact entry at {path}: {kind}")]
144    UnsupportedArtifactEntry {
145        /// Entry path.
146        path: String,
147        /// Observed entry kind.
148        kind: String,
149    },
150}