diff --git a/rust/noosphere-ns/src/builder.rs b/rust/noosphere-ns/src/builder.rs index 58f5dc962..007c3accb 100644 --- a/rust/noosphere-ns/src/builder.rs +++ b/rust/noosphere-ns/src/builder.rs @@ -39,7 +39,6 @@ where dht_config: DHTConfig, key_material: Option, store: Option>, - propagation_interval: u64, } impl NameSystemBuilder @@ -88,21 +87,39 @@ where self } + /// How long, in seconds, published records are replicated to + /// peers. Should be significantly shorter than `record_ttl`. + /// See [KademliaConfig::set_publication_interval](https://docs.rs/libp2p/latest/libp2p/kad/struct.KademliaConfig.html#method.set_publication_interval). + pub fn publication_interval(mut self, interval: u32) -> Self { + self.dht_config.publication_interval = interval; + self + } + /// How long, in seconds, until a network query times out. pub fn query_timeout(mut self, timeout: u32) -> Self { self.dht_config.query_timeout = timeout; self } - /// The Noosphere Store to use for reading and writing sphere data. - pub fn store(mut self, store: &SphereDb) -> Self { - self.store = Some(store.to_owned()); + /// How long, in seconds, records remain valid for. Should be significantly + /// longer than `publication_interval`. + /// See [KademliaConfig::set_record_ttl](https://docs.rs/libp2p/latest/libp2p/kad/struct.KademliaConfig.html#method.set_record_ttl). + pub fn record_ttl(mut self, interval: u32) -> Self { + self.dht_config.record_ttl = interval; self } - /// Default interval for hosted records to be propagated to the network. - pub fn propagation_interval(mut self, propagation_interval: u64) -> Self { - self.propagation_interval = propagation_interval; + /// How long, in seconds, stored records are replicated to + /// peers. Should be significantly shorter than `publication_interval`. + /// See [KademliaConfig::set_replication_interval](https://docs.rs/libp2p/latest/libp2p/kad/struct.KademliaConfig.html#method.set_replication_interval). + pub fn replication_interval(mut self, interval: u32) -> Self { + self.dht_config.replication_interval = interval; + self + } + + /// The Noosphere Store to use for reading and writing sphere data. + pub fn store(mut self, store: &SphereDb) -> Self { + self.store = Some(store.to_owned()); self } @@ -121,7 +138,6 @@ where store, self.bootstrap_peers.take(), self.dht_config, - self.propagation_interval, )) } } @@ -136,7 +152,6 @@ where dht_config: DHTConfig::default(), key_material: None, store: None, - propagation_interval: 60 * 60 * 24, // 1 day } } } @@ -171,11 +186,12 @@ mod tests { .bootstrap_interval(33) .peer_dialing_interval(11) .query_timeout(22) - .propagation_interval(3600) + .publication_interval(60 * 60 * 24 + 1) + .replication_interval(60 * 60 + 1) + .record_ttl(60 * 60 * 24 * 3 + 1) .build()?; assert_eq!(ns.key_material.0.as_ref(), key_material.0.as_ref()); - assert_eq!(ns._propagation_interval, 3600); assert_eq!(ns.bootstrap_peers.as_ref().unwrap().len(), 2); assert_eq!(ns.bootstrap_peers.as_ref().unwrap()[0], bootstrap_peers[0],); assert_eq!(ns.bootstrap_peers.as_ref().unwrap()[1], bootstrap_peers[1]); @@ -186,6 +202,9 @@ mod tests { assert_eq!(ns.dht_config.bootstrap_interval, 33); assert_eq!(ns.dht_config.peer_dialing_interval, 11); assert_eq!(ns.dht_config.query_timeout, 22); + assert_eq!(ns.dht_config.publication_interval, 60 * 60 * 24 + 1); + assert_eq!(ns.dht_config.replication_interval, 60 * 60 + 1); + assert_eq!(ns.dht_config.record_ttl, 60 * 60 * 24 * 3 + 1); if NameSystemBuilder::default().store(&store).build().is_ok() { panic!("key_material required."); diff --git a/rust/noosphere-ns/src/dht/config.rs b/rust/noosphere-ns/src/dht/config.rs index 6a7daef9f..5f503ec97 100644 --- a/rust/noosphere-ns/src/dht/config.rs +++ b/rust/noosphere-ns/src/dht/config.rs @@ -14,19 +14,35 @@ pub struct DHTConfig { /// dial peers found in its kbucket. Outside of tests, /// should not be lower than 5 seconds. pub peer_dialing_interval: u64, + /// How long, in seconds, published records are replicated to + /// peers. Should be significantly shorter than `record_ttl`. + /// See [KademliaConfig::set_publication_interval](https://docs.rs/libp2p/latest/libp2p/kad/struct.KademliaConfig.html#method.set_publication_interval). + pub publication_interval: u32, /// How long, in seconds, until an unsuccessful /// DHT query times out. pub query_timeout: u32, + /// How long, in seconds, stored records are replicated to + /// peers. Should be significantly shorter than `publication_interval`. + /// See [KademliaConfig::set_replication_interval](https://docs.rs/libp2p/latest/libp2p/kad/struct.KademliaConfig.html#method.set_replication_interval). + /// Only applies to value records. + pub replication_interval: u32, + /// How long, in seconds, records remain valid for. Should be significantly + /// longer than `publication_interval`. + /// See [KademliaConfig::set_record_ttl](https://docs.rs/libp2p/latest/libp2p/kad/struct.KademliaConfig.html#method.set_record_ttl). + pub record_ttl: u32, } impl Default for DHTConfig { /// Creates a new [DHTConfig] with defaults applied. fn default() -> Self { Self { - bootstrap_interval: 5 * 60, + bootstrap_interval: 5 * 60, // 5 mins listening_address: None, peer_dialing_interval: 5, - query_timeout: 5 * 60, + publication_interval: 60 * 60 * 24, // 1 day + query_timeout: 5 * 60, // 5 mins + replication_interval: 60 * 60, // 1 hour + record_ttl: 60 * 60 * 24 * 3, // 3 days } } } diff --git a/rust/noosphere-ns/src/dht/swarm.rs b/rust/noosphere-ns/src/dht/swarm.rs index 861446bcf..f080681a0 100644 --- a/rust/noosphere-ns/src/dht/swarm.rs +++ b/rust/noosphere-ns/src/dht/swarm.rs @@ -58,6 +58,21 @@ impl DHTBehaviour { // where we implement logic to validate/prune incoming records. cfg.set_record_filtering(KademliaStoreInserts::FilterBoth); + // These configurations only apply to Value records. + cfg.set_record_ttl(Some(Duration::from_secs(config.record_ttl.into()))); + cfg.set_publication_interval(Some(Duration::from_secs( + config.publication_interval.into(), + ))); + cfg.set_replication_interval(Some(Duration::from_secs( + config.replication_interval.into(), + ))); + + // These configurations are for Provider records. No replication interval available. + cfg.set_provider_record_ttl(Some(Duration::from_secs(config.record_ttl.into()))); + cfg.set_provider_publication_interval(Some(Duration::from_secs( + config.publication_interval.into(), + ))); + // TODO(#99): Use SphereFS storage let store = kad::record::store::MemoryStore::new(local_peer_id.to_owned()); Kademlia::with_config(local_peer_id.to_owned(), store, cfg) diff --git a/rust/noosphere-ns/src/name_system.rs b/rust/noosphere-ns/src/name_system.rs index 4ea74b9d4..712477575 100644 --- a/rust/noosphere-ns/src/name_system.rs +++ b/rust/noosphere-ns/src/name_system.rs @@ -33,8 +33,6 @@ where pub(crate) dht_config: DHTConfig, /// Key of the NameSystem's sphere. pub(crate) key_material: Ed25519KeyMaterial, - /// In seconds, the interval that hosted records are propagated on the network. - pub(crate) _propagation_interval: u64, pub(crate) store: SphereDb, /// Map of sphere DIDs to [NSRecord] hosted/propagated by this name system. hosted_records: HashMap, @@ -54,14 +52,12 @@ where store: SphereDb, bootstrap_peers: Option>, dht_config: DHTConfig, - _propagation_interval: u64, ) -> Self { NameSystem { key_material, store, bootstrap_peers, dht_config, - _propagation_interval, dht: None, hosted_records: HashMap::new(), resolved_records: HashMap::new(), @@ -95,8 +91,7 @@ where } /// Propagates all hosted records on nearby peers in the DHT network. - /// Automatically called every `crate::NameSystemBuilder::propagation_interval` seconds (TBD), - /// but can be manually called to republish records to the network. + /// Automatically propagated by the intervals configured in [crate::NameSystemBuilder]. /// /// Can fail if NameSystem is not connected or if no peers can be found. pub async fn propagate_records(&self) -> Result<()> { diff --git a/rust/noosphere-ns/tests/ns_test.rs b/rust/noosphere-ns/tests/ns_test.rs index 8200d9271..6cca6509a 100644 --- a/rust/noosphere-ns/tests/ns_test.rs +++ b/rust/noosphere-ns/tests/ns_test.rs @@ -68,7 +68,6 @@ async fn generate_name_systems_network( let ns: NameSystem = NameSystemBuilder::default() .key_material(&ns_key) .store(&store) - .propagation_interval(3600) .peer_dialing_interval(1) .bootstrap_peers(&bootstrap_addresses) .build()?;