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