Skip to main content

icydb_core/db/diagnostics/
model.rs

1//! Module: diagnostics::model
2//! Responsibility: diagnostics report DTO contracts and simple accessors.
3//! Does not own: store traversal, integrity scanning, or execution trace policy.
4//! Boundary: report assembly modules construct these DTOs; public callers read them.
5
6use crate::db::{
7    index::IndexState,
8    registry::{
9        StoreAllocationIdentityCapability, StoreCommitParticipation, StoreDurability,
10        StoreRecoveryCapability, StoreRuntimeStorageCapabilities, StoreSchemaMetadataCapability,
11    },
12};
13use candid::CandidType;
14use serde::Deserialize;
15
16#[cfg_attr(doc, doc = "StorageReport\n\nLive storage snapshot payload.")]
17#[derive(CandidType, Clone, Debug, Default, Deserialize)]
18pub struct StorageReport {
19    pub(crate) storage_data: Vec<DataStoreSnapshot>,
20    pub(crate) storage_index: Vec<IndexStoreSnapshot>,
21    pub(crate) schema_storage: Vec<SchemaStoreSnapshot>,
22    pub(crate) entity_storage: Vec<EntitySnapshot>,
23    pub(crate) corrupted_keys: u64,
24    pub(crate) corrupted_entries: u64,
25}
26
27#[cfg_attr(
28    doc,
29    doc = "IntegrityTotals\n\nAggregated integrity-scan counters across all stores."
30)]
31#[derive(CandidType, Clone, Debug, Default, Deserialize)]
32pub struct IntegrityTotals {
33    pub(crate) data_rows_scanned: u64,
34    pub(crate) index_entries_scanned: u64,
35    pub(crate) corrupted_data_keys: u64,
36    pub(crate) corrupted_data_rows: u64,
37    pub(crate) corrupted_index_keys: u64,
38    pub(crate) corrupted_index_entries: u64,
39    pub(crate) missing_index_entries: u64,
40    pub(crate) divergent_index_entries: u64,
41    pub(crate) orphan_index_references: u64,
42    pub(crate) misuse_findings: u64,
43}
44
45impl IntegrityTotals {
46    pub(super) const fn add_store_snapshot(&mut self, store: &IntegrityStoreSnapshot) {
47        self.data_rows_scanned = self
48            .data_rows_scanned
49            .saturating_add(store.data_rows_scanned);
50        self.index_entries_scanned = self
51            .index_entries_scanned
52            .saturating_add(store.index_entries_scanned);
53        self.corrupted_data_keys = self
54            .corrupted_data_keys
55            .saturating_add(store.corrupted_data_keys);
56        self.corrupted_data_rows = self
57            .corrupted_data_rows
58            .saturating_add(store.corrupted_data_rows);
59        self.corrupted_index_keys = self
60            .corrupted_index_keys
61            .saturating_add(store.corrupted_index_keys);
62        self.corrupted_index_entries = self
63            .corrupted_index_entries
64            .saturating_add(store.corrupted_index_entries);
65        self.missing_index_entries = self
66            .missing_index_entries
67            .saturating_add(store.missing_index_entries);
68        self.divergent_index_entries = self
69            .divergent_index_entries
70            .saturating_add(store.divergent_index_entries);
71        self.orphan_index_references = self
72            .orphan_index_references
73            .saturating_add(store.orphan_index_references);
74        self.misuse_findings = self.misuse_findings.saturating_add(store.misuse_findings);
75    }
76
77    /// Return total number of data rows scanned.
78    #[must_use]
79    pub const fn data_rows_scanned(&self) -> u64 {
80        self.data_rows_scanned
81    }
82
83    /// Return total number of index entries scanned.
84    #[must_use]
85    pub const fn index_entries_scanned(&self) -> u64 {
86        self.index_entries_scanned
87    }
88
89    /// Return total number of corrupted data-key findings.
90    #[must_use]
91    pub const fn corrupted_data_keys(&self) -> u64 {
92        self.corrupted_data_keys
93    }
94
95    /// Return total number of corrupted data-row findings.
96    #[must_use]
97    pub const fn corrupted_data_rows(&self) -> u64 {
98        self.corrupted_data_rows
99    }
100
101    /// Return total number of corrupted index-key findings.
102    #[must_use]
103    pub const fn corrupted_index_keys(&self) -> u64 {
104        self.corrupted_index_keys
105    }
106
107    /// Return total number of corrupted index-entry findings.
108    #[must_use]
109    pub const fn corrupted_index_entries(&self) -> u64 {
110        self.corrupted_index_entries
111    }
112
113    /// Return total number of missing index-entry findings.
114    #[must_use]
115    pub const fn missing_index_entries(&self) -> u64 {
116        self.missing_index_entries
117    }
118
119    /// Return total number of divergent index-entry findings.
120    #[must_use]
121    pub const fn divergent_index_entries(&self) -> u64 {
122        self.divergent_index_entries
123    }
124
125    /// Return total number of orphan index-reference findings.
126    #[must_use]
127    pub const fn orphan_index_references(&self) -> u64 {
128        self.orphan_index_references
129    }
130
131    /// Return total number of misuse findings.
132    #[must_use]
133    pub const fn misuse_findings(&self) -> u64 {
134        self.misuse_findings
135    }
136}
137
138#[cfg_attr(
139    doc,
140    doc = "IntegrityStoreSnapshot\n\nPer-store integrity findings and scan counters."
141)]
142#[derive(CandidType, Clone, Debug, Default, Deserialize)]
143pub struct IntegrityStoreSnapshot {
144    pub(crate) path: String,
145    pub(crate) data_rows_scanned: u64,
146    pub(crate) index_entries_scanned: u64,
147    pub(crate) corrupted_data_keys: u64,
148    pub(crate) corrupted_data_rows: u64,
149    pub(crate) corrupted_index_keys: u64,
150    pub(crate) corrupted_index_entries: u64,
151    pub(crate) missing_index_entries: u64,
152    pub(crate) divergent_index_entries: u64,
153    pub(crate) orphan_index_references: u64,
154    pub(crate) misuse_findings: u64,
155}
156
157impl IntegrityStoreSnapshot {
158    /// Construct one empty store-level integrity snapshot.
159    #[must_use]
160    pub(super) fn new(path: String) -> Self {
161        Self {
162            path,
163            ..Self::default()
164        }
165    }
166
167    /// Borrow store path.
168    #[must_use]
169    pub const fn path(&self) -> &str {
170        self.path.as_str()
171    }
172
173    /// Return number of scanned data rows.
174    #[must_use]
175    pub const fn data_rows_scanned(&self) -> u64 {
176        self.data_rows_scanned
177    }
178
179    /// Return number of scanned index entries.
180    #[must_use]
181    pub const fn index_entries_scanned(&self) -> u64 {
182        self.index_entries_scanned
183    }
184
185    /// Return number of corrupted data-key findings.
186    #[must_use]
187    pub const fn corrupted_data_keys(&self) -> u64 {
188        self.corrupted_data_keys
189    }
190
191    /// Return number of corrupted data-row findings.
192    #[must_use]
193    pub const fn corrupted_data_rows(&self) -> u64 {
194        self.corrupted_data_rows
195    }
196
197    /// Return number of corrupted index-key findings.
198    #[must_use]
199    pub const fn corrupted_index_keys(&self) -> u64 {
200        self.corrupted_index_keys
201    }
202
203    /// Return number of corrupted index-entry findings.
204    #[must_use]
205    pub const fn corrupted_index_entries(&self) -> u64 {
206        self.corrupted_index_entries
207    }
208
209    /// Return number of missing index-entry findings.
210    #[must_use]
211    pub const fn missing_index_entries(&self) -> u64 {
212        self.missing_index_entries
213    }
214
215    /// Return number of divergent index-entry findings.
216    #[must_use]
217    pub const fn divergent_index_entries(&self) -> u64 {
218        self.divergent_index_entries
219    }
220
221    /// Return number of orphan index-reference findings.
222    #[must_use]
223    pub const fn orphan_index_references(&self) -> u64 {
224        self.orphan_index_references
225    }
226
227    /// Return number of misuse findings.
228    #[must_use]
229    pub const fn misuse_findings(&self) -> u64 {
230        self.misuse_findings
231    }
232}
233
234#[cfg_attr(
235    doc,
236    doc = "IntegrityReport\n\nFull integrity-scan output across all registered stores."
237)]
238#[derive(CandidType, Clone, Debug, Default, Deserialize)]
239pub struct IntegrityReport {
240    pub(crate) stores: Vec<IntegrityStoreSnapshot>,
241    pub(crate) totals: IntegrityTotals,
242}
243
244impl IntegrityReport {
245    /// Construct one integrity report payload.
246    #[must_use]
247    pub(super) const fn new(stores: Vec<IntegrityStoreSnapshot>, totals: IntegrityTotals) -> Self {
248        Self { stores, totals }
249    }
250
251    /// Borrow per-store integrity snapshots.
252    #[must_use]
253    pub const fn stores(&self) -> &[IntegrityStoreSnapshot] {
254        self.stores.as_slice()
255    }
256
257    /// Borrow aggregated integrity totals.
258    #[must_use]
259    pub const fn totals(&self) -> &IntegrityTotals {
260        &self.totals
261    }
262}
263
264impl StorageReport {
265    /// Construct one storage report payload.
266    #[must_use]
267    pub(super) const fn new(
268        storage_data: Vec<DataStoreSnapshot>,
269        storage_index: Vec<IndexStoreSnapshot>,
270        schema_storage: Vec<SchemaStoreSnapshot>,
271        entity_storage: Vec<EntitySnapshot>,
272        corrupted_keys: u64,
273        corrupted_entries: u64,
274    ) -> Self {
275        Self {
276            storage_data,
277            storage_index,
278            schema_storage,
279            entity_storage,
280            corrupted_keys,
281            corrupted_entries,
282        }
283    }
284
285    /// Borrow data-store snapshots.
286    #[must_use]
287    pub const fn storage_data(&self) -> &[DataStoreSnapshot] {
288        self.storage_data.as_slice()
289    }
290
291    /// Borrow index-store snapshots.
292    #[must_use]
293    pub const fn storage_index(&self) -> &[IndexStoreSnapshot] {
294        self.storage_index.as_slice()
295    }
296
297    /// Borrow schema-store snapshots.
298    #[must_use]
299    pub const fn schema_storage(&self) -> &[SchemaStoreSnapshot] {
300        self.schema_storage.as_slice()
301    }
302
303    /// Borrow entity-level storage snapshots.
304    #[must_use]
305    pub const fn entity_storage(&self) -> &[EntitySnapshot] {
306        self.entity_storage.as_slice()
307    }
308
309    /// Return count of corrupted decoded data keys.
310    #[must_use]
311    pub const fn corrupted_keys(&self) -> u64 {
312        self.corrupted_keys
313    }
314
315    /// Return count of corrupted index entries.
316    #[must_use]
317    pub const fn corrupted_entries(&self) -> u64 {
318        self.corrupted_entries
319    }
320}
321
322#[cfg_attr(doc, doc = "SchemaStoreSnapshot\n\nSchema-store diagnostic row.")]
323#[derive(CandidType, Clone, Debug, Default, Deserialize)]
324pub struct SchemaStoreSnapshot {
325    pub(crate) path: String,
326    pub(crate) storage: StoreSnapshotStorageMode,
327    pub(crate) allocation: StoreAllocationIdentityCapability,
328    pub(crate) durability: StoreDurability,
329    pub(crate) commit: StoreCommitParticipation,
330    pub(crate) recovery: StoreRecoveryCapability,
331    pub(crate) schema_metadata: StoreSchemaMetadataCapability,
332    pub(crate) memory_id: Option<u8>,
333    pub(crate) stable_key: Option<String>,
334    pub(crate) schema_version: Option<u32>,
335    pub(crate) schema_fingerprint_method_version: Option<u8>,
336    pub(crate) schema_fingerprint: Option<String>,
337    pub(crate) entity_count: u64,
338}
339
340/// Diagnostic storage mode reported for one store-role snapshot.
341///
342/// This is observability metadata only. It does not participate in allocation
343/// identity, stable-key generation, or durable row/index/schema storage ABI.
344#[derive(CandidType, Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq)]
345pub enum StoreSnapshotStorageMode {
346    Heap,
347    #[default]
348    Journaled,
349}
350
351impl StoreSnapshotStorageMode {
352    /// Return the user-facing storage mode label.
353    #[must_use]
354    pub const fn as_str(self) -> &'static str {
355        match self {
356            Self::Heap => "heap",
357            Self::Journaled => "journaled",
358        }
359    }
360}
361
362#[derive(Clone, Debug, Eq, PartialEq)]
363pub(super) struct StoreSnapshotAllocationIdentity {
364    memory_id: u8,
365    stable_key: String,
366}
367
368impl StoreSnapshotAllocationIdentity {
369    pub(super) const fn new(memory_id: u8, stable_key: String) -> Self {
370        Self {
371            memory_id,
372            stable_key,
373        }
374    }
375
376    const fn memory_id(&self) -> u8 {
377        self.memory_id
378    }
379}
380
381#[derive(Clone, Debug, Default, Eq, PartialEq)]
382pub(super) struct StoreSnapshotSchemaMetadata {
383    version: Option<u32>,
384    fingerprint_method_version: Option<u8>,
385    fingerprint: Option<String>,
386}
387
388impl StoreSnapshotSchemaMetadata {
389    pub(super) const fn absent() -> Self {
390        Self {
391            version: None,
392            fingerprint_method_version: None,
393            fingerprint: None,
394        }
395    }
396
397    pub(super) const fn new(
398        schema_version: u32,
399        schema_fingerprint_method_version: u8,
400        schema_fingerprint: String,
401    ) -> Self {
402        Self {
403            version: Some(schema_version),
404            fingerprint_method_version: Some(schema_fingerprint_method_version),
405            fingerprint: Some(schema_fingerprint),
406        }
407    }
408
409    const fn schema_version(&self) -> Option<u32> {
410        self.version
411    }
412
413    const fn schema_fingerprint_method_version(&self) -> Option<u8> {
414        self.fingerprint_method_version
415    }
416
417    fn schema_fingerprint(&self) -> Option<String> {
418        self.fingerprint.clone()
419    }
420}
421
422#[derive(Clone, Debug, Eq, PartialEq)]
423struct StoreRoleSnapshotFields {
424    path: String,
425    storage: StoreSnapshotStorageMode,
426    allocation: StoreAllocationIdentityCapability,
427    durability: StoreDurability,
428    commit: StoreCommitParticipation,
429    recovery: StoreRecoveryCapability,
430    schema_metadata: StoreSchemaMetadataCapability,
431    memory_id: Option<u8>,
432    stable_key: Option<String>,
433    schema_version: Option<u32>,
434    schema_fingerprint_method_version: Option<u8>,
435    schema_fingerprint: Option<String>,
436}
437
438impl StoreRoleSnapshotFields {
439    fn new(
440        path: String,
441        storage: StoreSnapshotStorageMode,
442        capabilities: StoreRuntimeStorageCapabilities,
443        allocation: Option<StoreSnapshotAllocationIdentity>,
444        schema_metadata: StoreSnapshotSchemaMetadata,
445    ) -> Self {
446        let (memory_id, stable_key) = match allocation {
447            Some(allocation) => (Some(allocation.memory_id()), Some(allocation.stable_key)),
448            None => (None, None),
449        };
450        Self {
451            path,
452            storage,
453            allocation: capabilities.allocation_identity(),
454            durability: capabilities.durability(),
455            commit: capabilities.commit_participation(),
456            recovery: capabilities.recovery(),
457            schema_metadata: capabilities.schema_metadata(),
458            memory_id,
459            stable_key,
460            schema_version: schema_metadata.schema_version(),
461            schema_fingerprint_method_version: schema_metadata.schema_fingerprint_method_version(),
462            schema_fingerprint: schema_metadata.schema_fingerprint(),
463        }
464    }
465}
466
467#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
468pub(super) struct IndexStoreSnapshotStats {
469    entries: u64,
470    user_entries: u64,
471    system_entries: u64,
472    memory_bytes: u64,
473    state: IndexState,
474}
475
476impl IndexStoreSnapshotStats {
477    pub(super) const fn new(
478        entries: u64,
479        user_entries: u64,
480        system_entries: u64,
481        memory_bytes: u64,
482        state: IndexState,
483    ) -> Self {
484        Self {
485            entries,
486            user_entries,
487            system_entries,
488            memory_bytes,
489            state,
490        }
491    }
492}
493
494impl SchemaStoreSnapshot {
495    /// Construct one schema-store diagnostic row.
496    #[must_use]
497    pub(super) fn new(
498        path: String,
499        storage: StoreSnapshotStorageMode,
500        capabilities: StoreRuntimeStorageCapabilities,
501        allocation: Option<StoreSnapshotAllocationIdentity>,
502        schema_metadata: StoreSnapshotSchemaMetadata,
503        entity_count: u64,
504    ) -> Self {
505        let fields =
506            StoreRoleSnapshotFields::new(path, storage, capabilities, allocation, schema_metadata);
507        Self {
508            path: fields.path,
509            storage: fields.storage,
510            allocation: fields.allocation,
511            durability: fields.durability,
512            commit: fields.commit,
513            recovery: fields.recovery,
514            schema_metadata: fields.schema_metadata,
515            memory_id: fields.memory_id,
516            stable_key: fields.stable_key,
517            schema_version: fields.schema_version,
518            schema_fingerprint_method_version: fields.schema_fingerprint_method_version,
519            schema_fingerprint: fields.schema_fingerprint,
520            entity_count,
521        }
522    }
523
524    /// Borrow store path.
525    #[must_use]
526    pub const fn path(&self) -> &str {
527        self.path.as_str()
528    }
529
530    /// Return diagnostic storage mode.
531    #[must_use]
532    pub const fn storage(&self) -> StoreSnapshotStorageMode {
533        self.storage
534    }
535
536    /// Return allocation-identity capability metadata.
537    #[must_use]
538    pub const fn allocation(&self) -> StoreAllocationIdentityCapability {
539        self.allocation
540    }
541
542    /// Return durability capability metadata.
543    #[must_use]
544    pub const fn durability(&self) -> StoreDurability {
545        self.durability
546    }
547
548    /// Return commit participation capability metadata.
549    #[must_use]
550    pub const fn commit(&self) -> StoreCommitParticipation {
551        self.commit
552    }
553
554    /// Return recovery capability metadata.
555    #[must_use]
556    pub const fn recovery(&self) -> StoreRecoveryCapability {
557        self.recovery
558    }
559
560    /// Return schema-metadata persistence capability metadata.
561    #[must_use]
562    pub const fn schema_metadata(&self) -> StoreSchemaMetadataCapability {
563        self.schema_metadata
564    }
565
566    /// Return stable-memory manager ID, when generated wiring supplied it.
567    #[must_use]
568    pub const fn memory_id(&self) -> Option<u8> {
569        self.memory_id
570    }
571
572    /// Return durable stable-memory key, when generated wiring supplied it.
573    #[must_use]
574    pub const fn stable_key(&self) -> Option<&str> {
575        match &self.stable_key {
576            Some(value) => Some(value.as_str()),
577            None => None,
578        }
579    }
580
581    /// Return accepted schema/catalog version, when known.
582    #[must_use]
583    pub const fn schema_version(&self) -> Option<u32> {
584        self.schema_version
585    }
586
587    /// Return accepted schema/catalog fingerprint method version, when known.
588    #[must_use]
589    pub const fn schema_fingerprint_method_version(&self) -> Option<u8> {
590        self.schema_fingerprint_method_version
591    }
592
593    /// Return accepted schema/catalog fingerprint, when known.
594    #[must_use]
595    pub const fn schema_fingerprint(&self) -> Option<&str> {
596        match &self.schema_fingerprint {
597            Some(value) => Some(value.as_str()),
598            None => None,
599        }
600    }
601
602    /// Return number of entity schemas represented in this schema catalog.
603    #[must_use]
604    pub const fn entity_count(&self) -> u64 {
605        self.entity_count
606    }
607}
608
609#[cfg_attr(doc, doc = "DataStoreSnapshot\n\nData-store snapshot row.")]
610#[derive(CandidType, Clone, Debug, Default, Deserialize)]
611pub struct DataStoreSnapshot {
612    pub(crate) path: String,
613    pub(crate) storage: StoreSnapshotStorageMode,
614    pub(crate) allocation: StoreAllocationIdentityCapability,
615    pub(crate) durability: StoreDurability,
616    pub(crate) commit: StoreCommitParticipation,
617    pub(crate) recovery: StoreRecoveryCapability,
618    pub(crate) schema_metadata: StoreSchemaMetadataCapability,
619    pub(crate) memory_id: Option<u8>,
620    pub(crate) stable_key: Option<String>,
621    pub(crate) schema_version: Option<u32>,
622    pub(crate) schema_fingerprint_method_version: Option<u8>,
623    pub(crate) schema_fingerprint: Option<String>,
624    pub(crate) entries: u64,
625    pub(crate) memory_bytes: u64,
626}
627
628impl DataStoreSnapshot {
629    /// Construct one data-store snapshot row.
630    #[must_use]
631    pub(super) fn new(
632        path: String,
633        storage: StoreSnapshotStorageMode,
634        capabilities: StoreRuntimeStorageCapabilities,
635        allocation: Option<StoreSnapshotAllocationIdentity>,
636        schema_metadata: StoreSnapshotSchemaMetadata,
637        entries: u64,
638        memory_bytes: u64,
639    ) -> Self {
640        let fields =
641            StoreRoleSnapshotFields::new(path, storage, capabilities, allocation, schema_metadata);
642        Self {
643            path: fields.path,
644            storage: fields.storage,
645            allocation: fields.allocation,
646            durability: fields.durability,
647            commit: fields.commit,
648            recovery: fields.recovery,
649            schema_metadata: fields.schema_metadata,
650            memory_id: fields.memory_id,
651            stable_key: fields.stable_key,
652            schema_version: fields.schema_version,
653            schema_fingerprint_method_version: fields.schema_fingerprint_method_version,
654            schema_fingerprint: fields.schema_fingerprint,
655            entries,
656            memory_bytes,
657        }
658    }
659
660    /// Borrow store path.
661    #[must_use]
662    pub const fn path(&self) -> &str {
663        self.path.as_str()
664    }
665
666    /// Return diagnostic storage mode.
667    #[must_use]
668    pub const fn storage(&self) -> StoreSnapshotStorageMode {
669        self.storage
670    }
671
672    /// Return allocation-identity capability metadata.
673    #[must_use]
674    pub const fn allocation(&self) -> StoreAllocationIdentityCapability {
675        self.allocation
676    }
677
678    /// Return durability capability metadata.
679    #[must_use]
680    pub const fn durability(&self) -> StoreDurability {
681        self.durability
682    }
683
684    /// Return commit participation capability metadata.
685    #[must_use]
686    pub const fn commit(&self) -> StoreCommitParticipation {
687        self.commit
688    }
689
690    /// Return recovery capability metadata.
691    #[must_use]
692    pub const fn recovery(&self) -> StoreRecoveryCapability {
693        self.recovery
694    }
695
696    /// Return schema-metadata persistence capability metadata.
697    #[must_use]
698    pub const fn schema_metadata(&self) -> StoreSchemaMetadataCapability {
699        self.schema_metadata
700    }
701
702    /// Return stable-memory manager ID, when generated wiring supplied it.
703    #[must_use]
704    pub const fn memory_id(&self) -> Option<u8> {
705        self.memory_id
706    }
707
708    /// Return durable stable-memory key, when generated wiring supplied it.
709    #[must_use]
710    pub const fn stable_key(&self) -> Option<&str> {
711        match &self.stable_key {
712            Some(value) => Some(value.as_str()),
713            None => None,
714        }
715    }
716
717    /// Return accepted schema/catalog version, when known.
718    #[must_use]
719    pub const fn schema_version(&self) -> Option<u32> {
720        self.schema_version
721    }
722
723    /// Return accepted schema/catalog fingerprint method version, when known.
724    #[must_use]
725    pub const fn schema_fingerprint_method_version(&self) -> Option<u8> {
726        self.schema_fingerprint_method_version
727    }
728
729    /// Return accepted schema/catalog fingerprint, when known.
730    #[must_use]
731    pub const fn schema_fingerprint(&self) -> Option<&str> {
732        match &self.schema_fingerprint {
733            Some(value) => Some(value.as_str()),
734            None => None,
735        }
736    }
737
738    /// Return row count.
739    #[must_use]
740    pub const fn entries(&self) -> u64 {
741        self.entries
742    }
743
744    /// Return memory usage in bytes.
745    #[must_use]
746    pub const fn memory_bytes(&self) -> u64 {
747        self.memory_bytes
748    }
749}
750
751#[cfg_attr(doc, doc = "IndexStoreSnapshot\n\nIndex-store snapshot row.")]
752#[derive(CandidType, Clone, Debug, Default, Deserialize)]
753pub struct IndexStoreSnapshot {
754    pub(crate) path: String,
755    pub(crate) storage: StoreSnapshotStorageMode,
756    pub(crate) allocation: StoreAllocationIdentityCapability,
757    pub(crate) durability: StoreDurability,
758    pub(crate) commit: StoreCommitParticipation,
759    pub(crate) recovery: StoreRecoveryCapability,
760    pub(crate) schema_metadata: StoreSchemaMetadataCapability,
761    pub(crate) memory_id: Option<u8>,
762    pub(crate) stable_key: Option<String>,
763    pub(crate) schema_version: Option<u32>,
764    pub(crate) schema_fingerprint_method_version: Option<u8>,
765    pub(crate) schema_fingerprint: Option<String>,
766    pub(crate) entries: u64,
767    pub(crate) user_entries: u64,
768    pub(crate) system_entries: u64,
769    pub(crate) memory_bytes: u64,
770    pub(crate) state: IndexState,
771}
772
773impl IndexStoreSnapshot {
774    /// Construct one index-store snapshot row.
775    #[must_use]
776    pub(super) fn new(
777        path: String,
778        storage: StoreSnapshotStorageMode,
779        capabilities: StoreRuntimeStorageCapabilities,
780        allocation: Option<StoreSnapshotAllocationIdentity>,
781        schema_metadata: StoreSnapshotSchemaMetadata,
782        stats: IndexStoreSnapshotStats,
783    ) -> Self {
784        let fields =
785            StoreRoleSnapshotFields::new(path, storage, capabilities, allocation, schema_metadata);
786        Self {
787            path: fields.path,
788            storage: fields.storage,
789            allocation: fields.allocation,
790            durability: fields.durability,
791            commit: fields.commit,
792            recovery: fields.recovery,
793            schema_metadata: fields.schema_metadata,
794            memory_id: fields.memory_id,
795            stable_key: fields.stable_key,
796            schema_version: fields.schema_version,
797            schema_fingerprint_method_version: fields.schema_fingerprint_method_version,
798            schema_fingerprint: fields.schema_fingerprint,
799            entries: stats.entries,
800            user_entries: stats.user_entries,
801            system_entries: stats.system_entries,
802            memory_bytes: stats.memory_bytes,
803            state: stats.state,
804        }
805    }
806
807    /// Borrow store path.
808    #[must_use]
809    pub const fn path(&self) -> &str {
810        self.path.as_str()
811    }
812
813    /// Return diagnostic storage mode.
814    #[must_use]
815    pub const fn storage(&self) -> StoreSnapshotStorageMode {
816        self.storage
817    }
818
819    /// Return allocation-identity capability metadata.
820    #[must_use]
821    pub const fn allocation(&self) -> StoreAllocationIdentityCapability {
822        self.allocation
823    }
824
825    /// Return durability capability metadata.
826    #[must_use]
827    pub const fn durability(&self) -> StoreDurability {
828        self.durability
829    }
830
831    /// Return commit participation capability metadata.
832    #[must_use]
833    pub const fn commit(&self) -> StoreCommitParticipation {
834        self.commit
835    }
836
837    /// Return recovery capability metadata.
838    #[must_use]
839    pub const fn recovery(&self) -> StoreRecoveryCapability {
840        self.recovery
841    }
842
843    /// Return schema-metadata persistence capability metadata.
844    #[must_use]
845    pub const fn schema_metadata(&self) -> StoreSchemaMetadataCapability {
846        self.schema_metadata
847    }
848
849    /// Return stable-memory manager ID, when generated wiring supplied it.
850    #[must_use]
851    pub const fn memory_id(&self) -> Option<u8> {
852        self.memory_id
853    }
854
855    /// Return durable stable-memory key, when generated wiring supplied it.
856    #[must_use]
857    pub const fn stable_key(&self) -> Option<&str> {
858        match &self.stable_key {
859            Some(value) => Some(value.as_str()),
860            None => None,
861        }
862    }
863
864    /// Return accepted schema/catalog version, when known.
865    #[must_use]
866    pub const fn schema_version(&self) -> Option<u32> {
867        self.schema_version
868    }
869
870    /// Return accepted schema/catalog fingerprint method version, when known.
871    #[must_use]
872    pub const fn schema_fingerprint_method_version(&self) -> Option<u8> {
873        self.schema_fingerprint_method_version
874    }
875
876    /// Return accepted schema/catalog fingerprint, when known.
877    #[must_use]
878    pub const fn schema_fingerprint(&self) -> Option<&str> {
879        match &self.schema_fingerprint {
880            Some(value) => Some(value.as_str()),
881            None => None,
882        }
883    }
884
885    /// Return total entry count.
886    #[must_use]
887    pub const fn entries(&self) -> u64 {
888        self.entries
889    }
890
891    /// Return user-namespace entry count.
892    #[must_use]
893    pub const fn user_entries(&self) -> u64 {
894        self.user_entries
895    }
896
897    /// Return system-namespace entry count.
898    #[must_use]
899    pub const fn system_entries(&self) -> u64 {
900        self.system_entries
901    }
902
903    /// Return memory usage in bytes.
904    #[must_use]
905    pub const fn memory_bytes(&self) -> u64 {
906        self.memory_bytes
907    }
908
909    /// Return the current explicit runtime lifecycle state for this index
910    /// store snapshot.
911    #[must_use]
912    pub const fn state(&self) -> IndexState {
913        self.state
914    }
915}
916
917#[cfg_attr(doc, doc = "EntitySnapshot\n\nPer-entity storage snapshot row.")]
918#[derive(CandidType, Clone, Debug, Default, Deserialize)]
919pub struct EntitySnapshot {
920    pub(crate) store: String,
921
922    pub(crate) path: String,
923
924    pub(crate) entries: u64,
925
926    pub(crate) memory_bytes: u64,
927}
928
929impl EntitySnapshot {
930    /// Construct one entity-storage snapshot row.
931    #[must_use]
932    pub(super) const fn new(store: String, path: String, entries: u64, memory_bytes: u64) -> Self {
933        Self {
934            store,
935            path,
936            entries,
937            memory_bytes,
938        }
939    }
940
941    /// Borrow store path.
942    #[must_use]
943    pub const fn store(&self) -> &str {
944        self.store.as_str()
945    }
946
947    /// Borrow entity path.
948    #[must_use]
949    pub const fn path(&self) -> &str {
950        self.path.as_str()
951    }
952
953    /// Return row count.
954    #[must_use]
955    pub const fn entries(&self) -> u64 {
956        self.entries
957    }
958
959    /// Return memory usage in bytes.
960    #[must_use]
961    pub const fn memory_bytes(&self) -> u64 {
962        self.memory_bytes
963    }
964}