swim_rs/
lib.rs

1//! # swim-rs
2//!
3//! `swim-rs` is an implementation of the [SWIM protocol](https://www.cs.cornell.edu/projects/Quicksilver/public_pdfs/SWIM.pdf) in Rust,
4//! designed for efficient and scalable cluster membership and failure detection in distributed systems.
5//!
6//! This library is based on the official SWIM protocol paper and includes optimizations such as:
7//!
8//! - **Piggybacking Instead of Multicasting**: Reduces network overhead by attaching membership updates to periodic messages rather than sending separate multicast messages.
9//! - **Round-Robin Member Selection**: Ensures uniform probing of cluster members for health checks, improving detection accuracy.
10//! - **Suspicion Mechanism**: Introduces an intermediate state between alive and dead, reducing false positives in failure detection.
11//!
12//! ## Basic Example
13//!
14//! The following example demonstrates how to create two nodes in the same cluster and run the SWIM protocol:
15//!
16//! ```rust,no_run
17//! use std::time::Duration;
18//!
19//! use swim_rs::{
20//!     api::{config::SwimConfig, swim::SwimCluster},
21//!     Result,
22//! };
23//!
24//! #[tokio::main]
25//! async fn main() -> Result<()> {
26//!     // Creates two nodes in the same cluster
27//!     let node1 = SwimCluster::try_new("127.0.0.1:8080", SwimConfig::new()).await?;
28//!     let node2 = SwimCluster::try_new(
29//!         "127.0.0.1:8081",
30//!         SwimConfig::builder()
31//!             .with_known_peers(["127.0.0.1:8080"])
32//!             .build(),
33//!     )
34//!     .await?;
35//!
36//!     // Run the SWIM protocol in the background
37//!     node1.run().await;
38//!     node2.run().await;
39//!
40//!     // Simulate a long-running process or service
41//!     tokio::time::sleep(Duration::from_secs(12)).await;
42//!
43//!     Ok(())
44//! }
45//! ```
46//! ## Event Subscription Example
47//!
48//! The following example demonstrates how to subscribe to events emitted by nodes in the SWIM cluster.
49//!
50//! ```rust,no_run
51//! use std::time::Duration;
52//!
53//! use swim_rs::{
54//!     api::{config::SwimConfig, swim::SwimCluster},
55//!     Event, Result,
56//! };
57//!
58//! #[tokio::main]
59//! async fn main() -> Result<()> {
60//!     // Creates two nodes in the same cluster
61//!     let node1 = SwimCluster::try_new("127.0.0.1:8080", SwimConfig::new()).await?;
62//!     let node2 = SwimCluster::try_new(
63//!         "127.0.0.1:8081",
64//!         SwimConfig::builder()
65//!             .with_known_peers(["127.0.0.1:8080"])
66//!             .build(),
67//!     )
68//!     .await?;
69//!
70//!     // Run the SWIM protocol in the background
71//!     node1.run().await;
72//!     node2.run().await;
73//!
74//!     // Subscribe and receive events from node1
75//!     let mut rx1 = node1.subscribe();
76//!
77//!     // Handle events accordingly
78//!     while let Ok(event) = rx1.recv().await {
79//!        match event {
80//!            Event::NodeJoined(e) => tracing::info!("[{}] handle {:#?}", node1.addr(), e),
81//!            Event::NodeSuspected(e) => tracing::info!("[{}] handle {:#?}", node1.addr(), e),
82//!            Event::NodeRecovered(e) => tracing::info!("[{}] handle {:#?}", node1.addr(), e),
83//!            Event::NodeDeceased(e) => tracing::info!("[{}] handle {:#?}", node1.addr(), e),
84//!        }
85//!     }
86//!
87//!     // Simulate a long-running process or service
88//!     tokio::time::sleep(Duration::from_secs(12)).await;
89//!
90//!     Ok(())
91//! }
92//! ```
93//!
94//! ## Learn More
95//!
96//! - [SWIM Protocol Paper](https://www.cs.cornell.edu/projects/Quicksilver/public_pdfs/SWIM.pdf)
97//! - [GitHub Repository](https://github.com/marvinlanhenke/swim-rs)
98pub mod api;
99
100mod core;
101
102mod error;
103pub use error::Result;
104
105#[cfg(test)]
106#[path = "./test-utils/mod.rs"]
107#[doc(hidden)]
108mod test_utils;
109
110mod pb {
111    include!(concat!(env!("OUT_DIR"), "/v1.swim.rs"));
112}
113pub use pb::gossip::Event;
114pub use pb::gossip::{NodeDeceased, NodeJoined, NodeRecovered, NodeSuspected};
115pub use pb::NodeState;