use std::time::Duration;
use anyhow::Result;
use ed25519_dalek::SigningKey;
use iroh::{Endpoint, SecretKey};
use iroh_gossip::net::Gossip;
use distributed_topic_tracker::{
AutoDiscoveryGossip, BootstrapConfig, BubbleMergeConfig, Config, DefaultSecretRotation,
DhtConfig, MergeConfig, MessageOverlapMergeConfig, PublisherConfig, RecordPublisher,
RotationHandle, TimeoutConfig, TopicId,
};
fn config_builder() -> Config {
Config::builder()
.dht_config(
DhtConfig::builder()
.retries(3)
.base_retry_interval(Duration::from_secs(5))
.max_retry_jitter(Duration::from_secs(10))
.get_timeout(Duration::from_secs(10))
.put_timeout(Duration::from_secs(10))
.build(),
)
.bootstrap_config(
BootstrapConfig::builder()
.max_bootstrap_records(5)
.publish_record_on_startup(true)
.check_older_records_first_on_startup(false)
.discovery_poll_interval(Duration::from_millis(2000))
.no_peers_retry_interval(Duration::from_millis(1500))
.per_peer_join_settle_time(Duration::from_millis(100))
.join_confirmation_wait_time(Duration::from_millis(500))
.build(),
)
.max_join_peer_count(4)
.publisher_config(
PublisherConfig::builder()
.initial_delay(Duration::from_secs(10))
.base_interval(Duration::from_secs(10))
.max_jitter(Duration::from_secs(50))
.build(),
)
.merge_config(
MergeConfig::builder()
.bubble_merge(
BubbleMergeConfig::builder()
.min_neighbors(4)
.initial_interval(Duration::from_secs(30))
.base_interval(Duration::from_secs(60))
.max_jitter(Duration::from_secs(120))
.fail_topic_creation_on_merge_startup_failure(true)
.max_join_peers(2)
.build(),
)
.message_overlap_merge(
MessageOverlapMergeConfig::builder()
.initial_interval(Duration::from_secs(30))
.base_interval(Duration::from_secs(60))
.max_jitter(Duration::from_secs(120))
.fail_topic_creation_on_merge_startup_failure(true)
.max_join_peers(2)
.build(),
)
.build(),
)
.timeouts(
TimeoutConfig::builder()
.join_peer_timeout(Duration::from_secs(5))
.broadcast_neighbors_timeout(Duration::from_secs(5))
.broadcast_timeout(Duration::from_secs(5))
.build(),
)
.build()
}
#[tokio::main]
async fn main() -> Result<()> {
let secret_key = SecretKey::generate();
let signing_key = SigningKey::from_bytes(&secret_key.to_bytes());
let endpoint = Endpoint::builder(iroh::endpoint::presets::N0)
.secret_key(secret_key.clone())
.bind()
.await?;
let gossip = Gossip::builder().spawn(endpoint.clone());
let _router = iroh::protocol::Router::builder(endpoint.clone())
.accept(iroh_gossip::ALPN, gossip.clone())
.spawn();
let topic_id = TopicId::new("my-iroh-gossip-topic".to_string());
let initial_secret = b"my-initial-secret".to_vec();
let record_publisher =
RecordPublisher::builder(topic_id.clone(), signing_key.clone(), initial_secret)
.config(config_builder())
.secret_rotation(RotationHandle::new(DefaultSecretRotation))
.build();
let topic = gossip
.subscribe_and_join_with_auto_discovery(record_publisher)
.await?;
println!("[joined topic]");
let (_gossip_sender, _gossip_receiver) = topic.split().await?;
Ok(())
}