pub struct MemberlistStack<I, PD, T, D>where
I: Id + IdCodec + Data + Clone + Ord + Send + Sync + 'static,
PD: PlumtreeDelegate<I>,
T: Transport<Id = I>,
D: Delegate<Id = I, Address = T::ResolvedAddress>,{ /* private fields */ }Expand description
A complete Plumtree + Memberlist integration stack.
This struct combines:
PlumtreeMemberlistfor epidemic broadcast- Real
Memberlistinstance for SWIM gossip discovery - Automatic peer synchronization via
PlumtreeNodeDelegate
Use this when you want a fully integrated stack without manually wiring together the components.
§Type Parameters
I: Node identifier type (must implementId,IdCodec, etc.)PD: Plumtree delegate for message deliveryT: Memberlist transport (e.g.,NetTransport)D: The wrapped delegate type (created bywrap_delegate)
§Example
use memberlist_plumtree::{MemberlistStack, PlumtreeConfig, NoopDelegate};
use memberlist::{Memberlist, Options as MemberlistOptions};
use std::net::SocketAddr;
// Create the stack
let stack = MemberlistStack::builder(node_id, PlumtreeConfig::lan(), NoopDelegate)
.with_bind_address("127.0.0.1:0".parse().unwrap())
.build()
.await?;
// Join the cluster
let seed: SocketAddr = "192.168.1.100:7946".parse().unwrap();
stack.join(&[seed]).await?;
// Broadcast messages
stack.broadcast(b"hello").await?;Implementations§
Source§impl<I, PD, T, D> MemberlistStack<I, PD, T, D>
impl<I, PD, T, D> MemberlistStack<I, PD, T, D>
Sourcepub fn new(
pm: Arc<PlumtreeMemberlist<I, PD>>,
memberlist: Memberlist<T, D>,
advertise_addr: SocketAddr,
) -> Self
pub fn new( pm: Arc<PlumtreeMemberlist<I, PD>>, memberlist: Memberlist<T, D>, advertise_addr: SocketAddr, ) -> Self
Create a new MemberlistStack from pre-built components.
This is a low-level constructor. Prefer using MemberlistStackBuilder for
a more ergonomic API.
Sourcepub fn plumtree(&self) -> &Arc<PlumtreeMemberlist<I, PD>>
pub fn plumtree(&self) -> &Arc<PlumtreeMemberlist<I, PD>>
Get a reference to the PlumtreeMemberlist.
Sourcepub fn memberlist(&self) -> &Memberlist<T, D>
pub fn memberlist(&self) -> &Memberlist<T, D>
Get a reference to the Memberlist.
Sourcepub fn advertise_address(&self) -> SocketAddr
pub fn advertise_address(&self) -> SocketAddr
Get the advertise address for this node.
Other nodes can use this address to join the cluster.
Sourcepub fn peer_stats(&self) -> PeerStats
pub fn peer_stats(&self) -> PeerStats
Get Plumtree peer statistics.
Sourcepub async fn num_members(&self) -> usize
pub async fn num_members(&self) -> usize
Get the number of online memberlist members.
Sourcepub async fn broadcast(
&self,
payload: impl Into<Bytes>,
) -> Result<MessageId, Error>
pub async fn broadcast( &self, payload: impl Into<Bytes>, ) -> Result<MessageId, Error>
Broadcast a message through Plumtree.
The message will be delivered to all nodes in the cluster via the epidemic broadcast tree.
Sourcepub async fn join(
&self,
seed_addrs: &[SocketAddr],
) -> Result<(), MemberlistStackError>
pub async fn join( &self, seed_addrs: &[SocketAddr], ) -> Result<(), MemberlistStackError>
Join the cluster via seed nodes.
This triggers automatic peer discovery via SWIM gossip. The PlumtreeNodeDelegate will automatically update Plumtree’s topology as nodes are discovered.
§Arguments
seed_addrs- Socket addresses of seed nodes to join through
§Example
let seeds = vec![
"192.168.1.100:7946".parse().unwrap(),
"192.168.1.101:7946".parse().unwrap(),
];
stack.join(&seeds).await?;Sourcepub async fn leave(
&self,
timeout: Duration,
) -> Result<bool, MemberlistStackError>
pub async fn leave( &self, timeout: Duration, ) -> Result<bool, MemberlistStackError>
Leave the cluster gracefully.
This notifies other nodes of the departure and waits for the specified timeout for the leave message to propagate.
Sourcepub async fn shutdown(&self) -> Result<(), MemberlistStackError>
pub async fn shutdown(&self) -> Result<(), MemberlistStackError>
Shutdown the entire stack.
This shuts down both Plumtree and Memberlist.
Sourcepub fn is_shutdown(&self) -> bool
pub fn is_shutdown(&self) -> bool
Check if the stack has been shut down.
Source§impl<I, PD, T, D> MemberlistStack<I, PD, T, D>where
I: Id + IdCodec + Data + Clone + Ord + Send + Sync + 'static,
PD: PlumtreeDelegate<I> + 'static,
T: Transport<Id = I> + 'static,
D: Delegate<Id = I, Address = T::ResolvedAddress> + 'static,
T::ResolvedAddress: From<SocketAddr>,
impl<I, PD, T, D> MemberlistStack<I, PD, T, D>where
I: Id + IdCodec + Data + Clone + Ord + Send + Sync + 'static,
PD: PlumtreeDelegate<I> + 'static,
T: Transport<Id = I> + 'static,
D: Delegate<Id = I, Address = T::ResolvedAddress> + 'static,
T::ResolvedAddress: From<SocketAddr>,
Sourcepub fn spawn_lazarus_task(&self, config: BridgeConfig) -> LazarusHandlewhere
I: Debug,
pub fn spawn_lazarus_task(&self, config: BridgeConfig) -> LazarusHandlewhere
I: Debug,
Spawn the Lazarus background task for automatic seed recovery.
This task periodically checks if any configured static seeds are missing from the cluster and attempts to rejoin them. This handles the “Ghost Seed” problem where a restarted seed node remains isolated because other nodes stopped probing it after marking it dead.
§Arguments
config- The bridge configuration containing static seeds and interval
§Returns
A LazarusHandle that can be used to check stats and shutdown the task.
§Example
let config = BridgeConfig::new()
.with_static_seeds(vec![
"192.168.1.100:7946".parse().unwrap(),
"192.168.1.101:7946".parse().unwrap(),
])
.with_lazarus_enabled(true)
.with_lazarus_interval(Duration::from_secs(30));
let handle = stack.spawn_lazarus_task(config);
// Later, check stats
let stats = handle.stats();
println!("Reconnections: {}", stats.reconnections);
// Shutdown when done
handle.shutdown();Sourcepub async fn save_peers_to_file(
&self,
path: &Path,
) -> Result<(), PersistenceError>
pub async fn save_peers_to_file( &self, path: &Path, ) -> Result<(), PersistenceError>
Save current cluster members to persistence file.
This should be called periodically or on graceful shutdown to save known peers for recovery after restart.
§Arguments
path- Path to save the peer list
Sourcepub fn load_bootstrap_addresses(config: &BridgeConfig) -> Vec<SocketAddr>
pub fn load_bootstrap_addresses(config: &BridgeConfig) -> Vec<SocketAddr>
Auto Trait Implementations§
impl<I, PD, T, D> Freeze for MemberlistStack<I, PD, T, D>
impl<I, PD, T, D> !RefUnwindSafe for MemberlistStack<I, PD, T, D>
impl<I, PD, T, D> Send for MemberlistStack<I, PD, T, D>
impl<I, PD, T, D> Sync for MemberlistStack<I, PD, T, D>
impl<I, PD, T, D> Unpin for MemberlistStack<I, PD, T, D>
impl<I, PD, T, D> !UnwindSafe for MemberlistStack<I, PD, T, D>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more