canic_backup/journal/
report.rs1use crate::journal::{ArtifactState, DownloadJournal, DownloadOperationMetrics, ResumeAction};
8
9use serde::{Deserialize, Serialize};
10
11impl DownloadJournal {
12 #[must_use]
14 pub fn resume_report(&self) -> JournalResumeReport {
15 let mut counts = JournalStateCounts::default();
16 let mut artifacts = Vec::with_capacity(self.artifacts.len());
17
18 for artifact in &self.artifacts {
19 counts.record(artifact.state, artifact.resume_action());
20 artifacts.push(ArtifactResumeReport {
21 canister_id: artifact.canister_id.clone(),
22 snapshot_id: artifact.snapshot_id.clone(),
23 state: artifact.state,
24 resume_action: artifact.resume_action(),
25 artifact_path: artifact.artifact_path.clone(),
26 temp_path: artifact.temp_path.clone(),
27 updated_at: artifact.updated_at.clone(),
28 });
29 }
30
31 JournalResumeReport {
32 backup_id: self.backup_id.clone(),
33 discovery_topology_hash: self.discovery_topology_hash.clone(),
34 pre_snapshot_topology_hash: self.pre_snapshot_topology_hash.clone(),
35 total_artifacts: self.artifacts.len(),
36 is_complete: counts.skip == self.artifacts.len(),
37 pending_artifacts: self.artifacts.len() - counts.skip,
38 counts,
39 operation_metrics: self.operation_metrics.clone(),
40 artifacts,
41 }
42 }
43}
44
45#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
53pub struct JournalResumeReport {
54 pub backup_id: String,
55 pub discovery_topology_hash: Option<String>,
56 pub pre_snapshot_topology_hash: Option<String>,
57 pub total_artifacts: usize,
58 pub is_complete: bool,
59 pub pending_artifacts: usize,
60 pub counts: JournalStateCounts,
61 pub operation_metrics: DownloadOperationMetrics,
62 pub artifacts: Vec<ArtifactResumeReport>,
63}
64
65#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
73pub struct JournalStateCounts {
74 pub created: usize,
75 pub downloaded: usize,
76 pub checksum_verified: usize,
77 pub durable: usize,
78 pub download: usize,
79 pub verify_checksum: usize,
80 pub finalize: usize,
81 pub skip: usize,
82}
83
84impl JournalStateCounts {
85 const fn record(&mut self, state: ArtifactState, action: ResumeAction) {
86 match state {
87 ArtifactState::Created => self.created += 1,
88 ArtifactState::Downloaded => self.downloaded += 1,
89 ArtifactState::ChecksumVerified => self.checksum_verified += 1,
90 ArtifactState::Durable => self.durable += 1,
91 }
92
93 match action {
94 ResumeAction::Download => self.download += 1,
95 ResumeAction::VerifyChecksum => self.verify_checksum += 1,
96 ResumeAction::Finalize => self.finalize += 1,
97 ResumeAction::Skip => self.skip += 1,
98 }
99 }
100}
101
102#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
110pub struct ArtifactResumeReport {
111 pub canister_id: String,
112 pub snapshot_id: String,
113 pub state: ArtifactState,
114 pub resume_action: ResumeAction,
115 pub artifact_path: String,
116 pub temp_path: Option<String>,
117 pub updated_at: String,
118}