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