aboutsummaryrefslogtreecommitdiffstats
path: root/src/persist.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/persist.rs')
-rw-r--r--src/persist.rs84
1 files changed, 84 insertions, 0 deletions
diff --git a/src/persist.rs b/src/persist.rs
new file mode 100644
index 0000000..8e733b0
--- /dev/null
+++ b/src/persist.rs
@@ -0,0 +1,84 @@
+//! Persistence traits for data and routing table.
+//!
+//! The library defines the traits; applications
+//! implement backends (SQLite, file, etc).
+
+use crate::error::Error;
+use crate::id::NodeId;
+use std::net::SocketAddr;
+
+/// Stored value record for persistence.
+#[derive(Debug, Clone)]
+pub struct StoredRecord {
+ pub key: Vec<u8>,
+ pub value: Vec<u8>,
+ pub target_id: NodeId,
+ pub source: NodeId,
+ pub ttl: u16,
+ pub is_unique: bool,
+}
+
+/// Contact record for routing table persistence.
+#[derive(Debug, Clone)]
+pub struct ContactRecord {
+ pub id: NodeId,
+ pub addr: SocketAddr,
+}
+
+/// Trait for persisting DHT stored values.
+///
+/// Implement this to survive restarts. The library
+/// calls `save` periodically and `load` on startup.
+pub trait DataPersistence {
+ /// Save all stored values.
+ fn save(&self, records: &[StoredRecord]) -> Result<(), Error>;
+
+ /// Load previously saved values.
+ fn load(&self) -> Result<Vec<StoredRecord>, Error>;
+}
+
+/// Trait for persisting the routing table.
+///
+/// Implement this for fast re-bootstrap after restart.
+pub trait RoutingPersistence {
+ /// Save known contacts.
+ fn save_contacts(&self, contacts: &[ContactRecord]) -> Result<(), Error>;
+
+ /// Load previously saved contacts.
+ fn load_contacts(&self) -> Result<Vec<ContactRecord>, Error>;
+}
+
+/// No-op persistence (default — no persistence).
+pub struct NoPersistence;
+
+impl DataPersistence for NoPersistence {
+ fn save(&self, _records: &[StoredRecord]) -> Result<(), Error> {
+ Ok(())
+ }
+ fn load(&self) -> Result<Vec<StoredRecord>, Error> {
+ Ok(Vec::new())
+ }
+}
+
+impl RoutingPersistence for NoPersistence {
+ fn save_contacts(&self, _contacts: &[ContactRecord]) -> Result<(), Error> {
+ Ok(())
+ }
+ fn load_contacts(&self) -> Result<Vec<ContactRecord>, Error> {
+ Ok(Vec::new())
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn no_persistence_save_load() {
+ let p = NoPersistence;
+ assert!(p.save(&[]).is_ok());
+ assert!(p.load().unwrap().is_empty());
+ assert!(p.save_contacts(&[]).is_ok());
+ assert!(p.load_contacts().unwrap().is_empty());
+ }
+}