Skip to main content

holos_tda/distributed/
model.rs

1use std::fmt;
2use std::path::PathBuf;
3
4use sha2::{Digest, Sha256};
5
6use crate::{CertificateLimits, RelativeInterfaceCertificate};
7
8/// Failure during durable interface execution or recovery.
9#[derive(Debug)]
10pub struct DistributedInterfaceError {
11    message: String,
12}
13
14impl DistributedInterfaceError {
15    pub(super) fn new(message: impl Into<String>) -> Self {
16        Self {
17            message: message.into(),
18        }
19    }
20
21    /// Description of the failed store or algebra rule.
22    pub fn message(&self) -> &str {
23        &self.message
24    }
25}
26
27impl fmt::Display for DistributedInterfaceError {
28    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
29        write!(formatter, "distributed interface: {}", self.message)
30    }
31}
32
33impl std::error::Error for DistributedInterfaceError {}
34
35/// SHA-256 identifier of one stored artifact.
36#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
37pub struct ArtifactId(pub(super) [u8; 32]);
38
39impl ArtifactId {
40    /// Compute the identifier of exact artifact bytes.
41    pub fn for_bytes(bytes: &[u8]) -> Self {
42        Self(Sha256::digest(bytes).into())
43    }
44
45    /// Construct an identifier from its 32-byte representation.
46    pub fn from_bytes(bytes: [u8; 32]) -> Self {
47        Self(bytes)
48    }
49
50    /// Raw identifier bytes.
51    pub fn as_bytes(&self) -> &[u8; 32] {
52        &self.0
53    }
54
55    /// Lowercase hexadecimal identifier.
56    pub fn to_hex(self) -> String {
57        let mut output = String::with_capacity(64);
58        for byte in self.0 {
59            use std::fmt::Write as _;
60            write!(output, "{byte:02x}").expect("writing to a string cannot fail");
61        }
62        output
63    }
64}
65
66impl fmt::Display for ArtifactId {
67    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
68        formatter.write_str(&self.to_hex())
69    }
70}
71
72/// Exact I/O and fold work for one distributed composition.
73#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
74pub struct DistributedInterfaceWork {
75    /// Shard artifacts in the job.
76    pub shards: usize,
77    /// Shard artifacts decoded during this invocation.
78    pub shards_loaded: usize,
79    /// Completed folds reused from durable progress.
80    pub folds_reused: usize,
81    /// New folds computed during this invocation.
82    pub folds_computed: usize,
83    /// Artifact bytes read from the store.
84    pub bytes_read: usize,
85    /// New artifact bytes written to the store.
86    pub bytes_written: usize,
87    /// Peak byte count of one accumulator and one shard.
88    pub peak_artifact_bytes: usize,
89}
90
91/// Commit record for one distributed interface result.
92#[derive(Debug, Clone, PartialEq, Eq)]
93pub struct DistributedInterfaceManifest {
94    pub(super) job: ArtifactId,
95    pub(super) max_dim: usize,
96    pub(super) modulus: u32,
97    pub(super) separator_vertices: Vec<usize>,
98    pub(super) output_protected_vertices: Vec<usize>,
99    pub(super) shards: Vec<ArtifactId>,
100    pub(super) folds: Vec<ArtifactId>,
101    pub(super) result: ArtifactId,
102}
103
104/// Completed distributed composition and its durable manifest.
105#[derive(Debug, Clone)]
106pub struct DistributedInterfaceCommit {
107    pub(super) manifest: DistributedInterfaceManifest,
108    pub(super) certificate: RelativeInterfaceCertificate,
109    pub(super) work: DistributedInterfaceWork,
110}
111
112impl DistributedInterfaceCommit {
113    /// Durable commit manifest.
114    pub fn manifest(&self) -> &DistributedInterfaceManifest {
115        &self.manifest
116    }
117
118    /// Composed relative-interface certificate.
119    pub fn certificate(&self) -> &RelativeInterfaceCertificate {
120        &self.certificate
121    }
122
123    /// I/O and fold work charged to this invocation.
124    pub fn work(&self) -> DistributedInterfaceWork {
125        self.work
126    }
127}
128
129/// Filesystem-backed content-addressed store for interface artifacts.
130#[derive(Debug, Clone)]
131pub struct DurableInterfaceStore {
132    pub(super) root: PathBuf,
133}
134
135pub(super) struct CommitPlan<'a> {
136    pub(super) job: ArtifactId,
137    pub(super) shard_ids: &'a [ArtifactId],
138    pub(super) separator_vertices: Vec<usize>,
139    pub(super) output_protected_vertices: Vec<usize>,
140    pub(super) intermediate_protected: Vec<usize>,
141    pub(super) limits: CertificateLimits,
142}
143
144pub(super) struct FoldState {
145    pub(super) accumulator: RelativeInterfaceCertificate,
146    pub(super) folds: Vec<ArtifactId>,
147    pub(super) next: usize,
148    pub(super) accumulator_bytes: Vec<u8>,
149}
150
151pub(super) struct PreparedCommit<'a> {
152    pub(super) plan: CommitPlan<'a>,
153    pub(super) first_id: ArtifactId,
154    pub(super) first: RelativeInterfaceCertificate,
155}
156
157pub(super) struct Progress {
158    pub(super) prefix: usize,
159    pub(super) accumulator: ArtifactId,
160    pub(super) folds: Vec<ArtifactId>,
161}