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