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 download_journal;
7mod effect_graph;
8mod file_lock;
9mod inventory;
10mod journal_lock;
11mod json;
12mod layout_lifetime;
13mod operation_plan;
14
15pub use artifact_commit::{ArtifactCommitOutcome, commit_artifact_directory};
16pub use attempt_journal::{AttemptJournalError, AttemptJournalGuard};
17pub use command_lifetime_lock::{
18    COMMAND_CUSTODY_DESCRIPTOR_ENV, CommandLifetimeLock, CommandLifetimeLockError,
19    CommandQuiescenceGuard,
20};
21pub use download_journal::{DownloadJournalError, DownloadJournalGuard};
22pub use effect_graph::{EffectGraphPersistenceError, create_effect_graph, read_effect_graph};
23pub use inventory::{InventoryError, create_inventory, read_inventory};
24pub use journal_lock::{JournalLock, JournalLockError};
25pub use json::{create_json_durable, read_json, write_json_durable};
26pub use layout_lifetime::{BackupLayoutGuard, MAX_RESTORE_REFERENCE_BYTES};
27pub use operation_plan::{
28    OperationPlanPersistenceError, create_operation_plan, read_operation_plan,
29};
30
31use crate::{model::artifacts::ChecksumError, ops::artifacts::ArtifactError};
32use std::io;
33use thiserror::Error;
34
35/// Typed local persistence failure.
36#[derive(Debug, Error)]
37pub enum PersistenceError {
38    /// An existing layout path no longer denotes the held directory.
39    #[error("backup layout changed while held: {path:?}")]
40    LayoutChanged {
41        /// Resolved layout location.
42        path: std::path::PathBuf,
43    },
44    /// A retained dependency document or journal location has an unsafe entry type.
45    #[error("unsafe restore reference entry: {path:?}")]
46    InvalidRestoreReferences {
47        /// Rejected local path.
48        path: std::path::PathBuf,
49    },
50    /// Restore dependency validation or an immutable retention transition failed.
51    #[error(transparent)]
52    RestoreReference(#[from] crate::model::restore_references::RestoreReferenceError),
53    /// Filesystem IO failed; publication may require local reconciliation.
54    #[error(transparent)]
55    Io(#[from] io::Error),
56    /// JSON encoding or decoding failed.
57    #[error(transparent)]
58    Json(#[from] serde_json::Error),
59    /// A machine record exceeds its caller-selected byte bound.
60    #[error("record exceeds byte limit {limit}")]
61    RecordTooLarge {
62        /// Maximum accepted bytes.
63        limit: u64,
64    },
65    /// Artifact traversal or streaming failed.
66    #[error(transparent)]
67    Artifact(#[from] ArtifactError),
68    /// Verified bytes do not match the expected checksum.
69    #[error(transparent)]
70    Checksum(#[from] ChecksumError),
71    /// Publication requires distinct siblings in one directory.
72    #[error("artifact commit paths must be distinct siblings: {temporary}, {canonical}")]
73    ArtifactCommitPathMismatch {
74        /// Retained staging path.
75        temporary: String,
76        /// Canonical destination.
77        canonical: String,
78    },
79    /// Both staging and canonical trees exist; neither is overwritten.
80    #[error("artifact commit has conflicting paths: {temporary}, {canonical}")]
81    ArtifactCommitPathConflict {
82        /// Retained staging path.
83        temporary: String,
84        /// Existing canonical destination.
85        canonical: String,
86    },
87    /// Neither expected tree exists.
88    #[error("artifact commit is missing both paths: {temporary}, {canonical}")]
89    ArtifactCommitPathMissing {
90        /// Missing staging path.
91        temporary: String,
92        /// Missing canonical destination.
93        canonical: String,
94    },
95    /// Atomic no-replace directory publication is unsupported.
96    #[error("durable artifact publication is unsupported on {platform}")]
97    ArtifactCommitUnsupportedPlatform {
98        /// Host platform name.
99        platform: &'static str,
100    },
101    /// Publication found an unsafe tree entry.
102    #[error("unsupported artifact entry at {path}: {kind}")]
103    UnsupportedArtifactEntry {
104        /// Entry path.
105        path: String,
106        /// Observed entry kind.
107        kind: String,
108    },
109}