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