Skip to main content

rings_core/inspect/
snapshot.rs

1use serde::Deserialize;
2use serde::Serialize;
3
4use super::compress_iter;
5use crate::dht::entry::Entry;
6use crate::dht::EntryStorage;
7use crate::dht::PeerRing;
8use crate::swarm::Swarm;
9
10/// Full runtime inspection snapshot for a swarm.
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct SwarmInspect {
13    /// Active peer connections known by the swarm.
14    pub peers: Vec<ConnectionInspect>,
15    /// DHT routing state for the local peer.
16    pub dht: DHTInspect,
17    /// Persistent DHT storage contents.
18    pub persistence_storage: StorageInspect,
19    /// Cache DHT storage contents.
20    pub cache_storage: StorageInspect,
21}
22
23/// Inspection snapshot for a single peer connection.
24#[derive(Debug, Clone, Serialize, Deserialize)]
25pub struct ConnectionInspect {
26    /// Remote DID as a display string.
27    pub did: String,
28    /// Connection state as a display string.
29    pub state: String,
30}
31
32/// Inspection snapshot for local DHT routing state.
33#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
34pub struct DHTInspect {
35    /// Local node DID.
36    pub did: String,
37    /// Current successor list.
38    pub successors: Vec<String>,
39    #[serde(default)]
40    /// Current predecessor, when known.
41    pub predecessor: Option<String>,
42    /// Compressed finger table ranges with optional DID values.
43    pub finger_table: Vec<(Option<String>, u64, u64)>,
44}
45
46/// Inspection snapshot for key value storage contents.
47#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
48pub struct StorageInspect {
49    /// Stored entries as `(key, entry)` pairs.
50    pub items: Vec<(String, Entry)>,
51}
52
53impl SwarmInspect {
54    /// Build a full inspection snapshot from `swarm`.
55    pub async fn inspect(swarm: &Swarm) -> Self {
56        let dht = DHTInspect::inspect(&swarm.dht());
57        let peers = swarm.peers();
58        let persistence_storage = StorageInspect::inspect_kv_storage(&swarm.dht().storage).await;
59        let cache_storage = StorageInspect::inspect_kv_storage(&swarm.dht().cache).await;
60
61        Self {
62            peers,
63            dht,
64            persistence_storage,
65            cache_storage,
66        }
67    }
68}
69
70impl DHTInspect {
71    /// Build a DHT inspection snapshot from a peer ring.
72    pub fn inspect(dht: &PeerRing) -> Self {
73        let did = dht.did.to_string();
74        let topology = dht.topology_state().ok();
75        let successors = topology
76            .as_ref()
77            .map(|state| {
78                state
79                    .successors
80                    .iter()
81                    .copied()
82                    .map(|s| s.to_string())
83                    .collect()
84            })
85            .unwrap_or_default();
86        let predecessor = topology
87            .as_ref()
88            .and_then(|state| state.predecessor)
89            .map(|predecessor| predecessor.to_string());
90        let finger_table = topology
91            .map(|state| {
92                compress_iter(
93                    state
94                        .fingers
95                        .into_iter()
96                        .map(|finger| finger.map(|did| did.to_string())),
97                )
98            })
99            .unwrap_or_default();
100
101        Self {
102            did,
103            successors,
104            predecessor,
105            finger_table,
106        }
107    }
108}
109
110impl StorageInspect {
111    /// Build a storage inspection snapshot from an entry storage handle.
112    pub async fn inspect_kv_storage(storage: &EntryStorage) -> Self {
113        Self {
114            items: storage
115                .get_all()
116                .await
117                .unwrap_or_default()
118                .into_iter()
119                .collect(),
120        }
121    }
122}