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