datum-cluster 0.10.0

Datum cluster membership over SWIM gossip
Documentation
#![forbid(unsafe_code)]
//! Cluster membership for Datum.
//!
//! This crate is intentionally a membership layer only. It wraps `foca` 1.x as
//! the private SWIM engine and keeps all foca identities, configuration, timers,
//! and notifications out of the public API. The public model mirrors the useful
//! Akka Cluster member states Datum needs before placement arrives:
//! [`MemberState::Joining`], [`MemberState::Up`], [`MemberState::Leaving`],
//! [`MemberState::Exiting`], [`MemberState::Down`], and
//! [`MemberState::Removed`].
//!
//! The implementation is split into two planes. The membership actor owns the
//! registry, state transitions, [`Signal`] current-state publication, lossless
//! [`Subscription`] event publication, and downing decisions. The gossip plane is
//! one Tokio task that owns the UDP socket and foca instance; it receives
//! datagrams, drains foca runtime sends/timers/notifications, and never spawns an
//! actor per packet.
//!
//! Current-state reads use `Signal<ClusterState>` because operators usually want
//! the latest immutable view without replay. Membership changes use
//! `Subscription<MemberEvent>` because active subscribers must observe every
//! accepted state transition in sequence. `Subscription` is bounded and
//! backpressures the publisher instead of dropping membership events.
//!
//! Failure detection and downing are deliberately separate. Foca suspicion marks
//! a member unreachable; a [`DowningProvider`] decides when that unreachable
//! member becomes [`MemberState::Down`]. The default [`TimeoutDowning`] is simple
//! and useful for tests and small deployments, but it is not a split-brain
//! resolver: v0.10 has no quorum, lease, or majority strategy. A split-brain
//! resolution provider is a named follow-up before placement can make strong
//! singleton or sharding claims.
//!
//! C3 placement uses a deterministic coordinator convention rather than an
//! election protocol: every node picks the oldest reachable `Up` member from
//! its local C1 view, tie-broken by node id. C1 does not assign Akka up numbers,
//! so v0.10 uses the propagated member incarnation as the age key. This is
//! deterministic for a shared view, but it is not fencing: under a partition
//! plus timeout downing, both sides can transiently have a coordinator. Quorum
//! or lease fencing is a v0.11+ follow-up.
//!
//! UDP is the v0.10 gossip transport. QUIC plus mTLS is deferred for the control
//! plane and future secure gossip transport; the public API is transport-neutral
//! so that change does not expose foca internals.

mod config;
mod downing;
mod error;
mod foca_driver;
mod model;
mod node;

pub use config::ClusterConfig;
pub use downing::{DowningProvider, TimeoutDowning};
pub use error::{ClusterError, ClusterResult};
pub use model::{ClusterState, Member, MemberEvent, MemberEventKind, MemberState};
pub use node::ClusterNode;

pub use datum::{Signal, Subscription};

/// The `datum-cluster` crate version.
pub const VERSION: &str = env!("CARGO_PKG_VERSION");