MemberlistStack

Struct MemberlistStack 

Source
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:

  • PlumtreeMemberlist for epidemic broadcast
  • Real Memberlist instance 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 implement Id, IdCodec, etc.)
  • PD: Plumtree delegate for message delivery
  • T: Memberlist transport (e.g., NetTransport)
  • D: The wrapped delegate type (created by wrap_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>
where I: Id + IdCodec + Data + Clone + Ord + Send + Sync + 'static, PD: PlumtreeDelegate<I>, T: Transport<Id = I>, D: Delegate<Id = I, Address = T::ResolvedAddress>,

Source

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.

Source

pub fn plumtree(&self) -> &Arc<PlumtreeMemberlist<I, PD>>

Get a reference to the PlumtreeMemberlist.

Source

pub fn memberlist(&self) -> &Memberlist<T, D>

Get a reference to the Memberlist.

Source

pub fn advertise_address(&self) -> SocketAddr

Get the advertise address for this node.

Other nodes can use this address to join the cluster.

Source

pub fn peer_stats(&self) -> PeerStats

Get Plumtree peer statistics.

Source

pub async fn num_members(&self) -> usize

Get the number of online memberlist members.

Source

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.

Source

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?;
Source

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.

Source

pub async fn shutdown(&self) -> Result<(), MemberlistStackError>

Shutdown the entire stack.

This shuts down both Plumtree and Memberlist.

Source

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>,

Source

pub fn spawn_lazarus_task(&self, config: BridgeConfig) -> LazarusHandle
where 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();
Source

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
Source

pub fn load_bootstrap_addresses(config: &BridgeConfig) -> Vec<SocketAddr>

Load persisted peers and combine with static seeds.

This provides a comprehensive list of potential bootstrap addresses.

§Arguments
  • config - Bridge configuration with persistence path and static seeds
§Returns

Combined list of unique addresses from both persistence and static seeds.

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> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more