//! Callback traits for cluster events use async_trait::async_trait; use chainfire_types::node::NodeInfo; use crate::kvs::KvEntry; /// Handler for cluster lifecycle events /// /// Implement this trait to receive notifications about cluster membership /// and leadership changes. #[async_trait] pub trait ClusterEventHandler: Send + Sync { /// Called when a node joins the cluster async fn on_node_joined(&self, _node: &NodeInfo) {} /// Called when a node leaves the cluster async fn on_node_left(&self, _node_id: u64, _reason: LeaveReason) {} /// Called when leadership changes async fn on_leader_changed(&self, _old_leader: Option, _new_leader: u64) {} /// Called when this node becomes leader async fn on_became_leader(&self) {} /// Called when this node loses leadership async fn on_lost_leadership(&self) {} /// Called when cluster membership changes async fn on_membership_changed(&self, _members: &[NodeInfo]) {} /// Called when a network partition is detected async fn on_partition_detected(&self, _reachable: &[u64], _unreachable: &[u64]) {} /// Called when cluster is ready (initial leader elected, etc.) async fn on_cluster_ready(&self) {} } /// Handler for KV store events /// /// Implement this trait to receive notifications about key-value changes. #[async_trait] pub trait KvEventHandler: Send + Sync { /// Called when a key is created or updated async fn on_key_changed( &self, _namespace: &str, _key: &[u8], _value: &[u8], _revision: u64, ) { } /// Called when a key is deleted async fn on_key_deleted(&self, _namespace: &str, _key: &[u8], _revision: u64) {} /// Called when multiple keys with a prefix are changed async fn on_prefix_changed(&self, _namespace: &str, _prefix: &[u8], _entries: &[KvEntry]) {} } /// Reason for node departure from the cluster #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum LeaveReason { /// Node left gracefully Graceful, /// Node timed out (failed to respond) Timeout, /// Network partition detected NetworkPartition, /// Node was explicitly evicted Evicted, /// Unknown reason Unknown, } impl std::fmt::Display for LeaveReason { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { LeaveReason::Graceful => write!(f, "graceful"), LeaveReason::Timeout => write!(f, "timeout"), LeaveReason::NetworkPartition => write!(f, "network_partition"), LeaveReason::Evicted => write!(f, "evicted"), LeaveReason::Unknown => write!(f, "unknown"), } } } /// A no-op event handler for when callbacks are not needed pub struct NoOpClusterEventHandler; #[async_trait] impl ClusterEventHandler for NoOpClusterEventHandler {} /// A no-op KV event handler pub struct NoOpKvEventHandler; #[async_trait] impl KvEventHandler for NoOpKvEventHandler {}