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;