- Remove gitlinks (160000 mode) for chainfire, flaredb, iam - Add workspace contents as regular tracked files - Update flake.nix to use simple paths instead of builtins.fetchGit This resolves the nix build failure where submodule directories appeared empty in the nix store. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
198 lines
5.4 KiB
Rust
198 lines
5.4 KiB
Rust
//! Event types and dispatcher
|
|
|
|
use std::sync::Arc;
|
|
|
|
use tokio::sync::broadcast;
|
|
|
|
use chainfire_types::node::NodeInfo;
|
|
|
|
use crate::callbacks::{ClusterEventHandler, KvEventHandler, LeaveReason};
|
|
|
|
/// Cluster-level events
|
|
#[derive(Debug, Clone)]
|
|
pub enum ClusterEvent {
|
|
/// A node joined the cluster
|
|
NodeJoined(NodeInfo),
|
|
|
|
/// A node left the cluster
|
|
NodeLeft {
|
|
/// The node ID that left
|
|
node_id: u64,
|
|
/// Why the node left
|
|
reason: LeaveReason,
|
|
},
|
|
|
|
/// Leadership changed
|
|
LeaderChanged {
|
|
/// Previous leader (None if no previous leader)
|
|
old: Option<u64>,
|
|
/// New leader
|
|
new: u64,
|
|
},
|
|
|
|
/// This node became the leader
|
|
BecameLeader,
|
|
|
|
/// This node lost leadership
|
|
LostLeadership,
|
|
|
|
/// Cluster membership changed
|
|
MembershipChanged(Vec<NodeInfo>),
|
|
|
|
/// Network partition detected
|
|
PartitionDetected {
|
|
/// Nodes that are reachable
|
|
reachable: Vec<u64>,
|
|
/// Nodes that are unreachable
|
|
unreachable: Vec<u64>,
|
|
},
|
|
|
|
/// Cluster is ready
|
|
ClusterReady,
|
|
}
|
|
|
|
/// KV store events
|
|
#[derive(Debug, Clone)]
|
|
pub enum KvEvent {
|
|
/// A key was created or updated
|
|
KeyChanged {
|
|
/// Namespace of the key
|
|
namespace: String,
|
|
/// The key that changed
|
|
key: Vec<u8>,
|
|
/// New value
|
|
value: Vec<u8>,
|
|
/// Revision number
|
|
revision: u64,
|
|
},
|
|
|
|
/// A key was deleted
|
|
KeyDeleted {
|
|
/// Namespace of the key
|
|
namespace: String,
|
|
/// The key that was deleted
|
|
key: Vec<u8>,
|
|
/// Revision number
|
|
revision: u64,
|
|
},
|
|
}
|
|
|
|
/// Event dispatcher that manages callbacks and event broadcasting
|
|
pub struct EventDispatcher {
|
|
cluster_handlers: Vec<Arc<dyn ClusterEventHandler>>,
|
|
kv_handlers: Vec<Arc<dyn KvEventHandler>>,
|
|
event_tx: broadcast::Sender<ClusterEvent>,
|
|
}
|
|
|
|
impl EventDispatcher {
|
|
/// Create a new event dispatcher
|
|
pub fn new() -> Self {
|
|
let (event_tx, _) = broadcast::channel(1024);
|
|
Self {
|
|
cluster_handlers: Vec::new(),
|
|
kv_handlers: Vec::new(),
|
|
event_tx,
|
|
}
|
|
}
|
|
|
|
/// Add a cluster event handler
|
|
pub fn add_cluster_handler(&mut self, handler: Arc<dyn ClusterEventHandler>) {
|
|
self.cluster_handlers.push(handler);
|
|
}
|
|
|
|
/// Add a KV event handler
|
|
pub fn add_kv_handler(&mut self, handler: Arc<dyn KvEventHandler>) {
|
|
self.kv_handlers.push(handler);
|
|
}
|
|
|
|
/// Get a subscriber for cluster events
|
|
pub fn subscribe(&self) -> broadcast::Receiver<ClusterEvent> {
|
|
self.event_tx.subscribe()
|
|
}
|
|
|
|
/// Dispatch a cluster event to all handlers
|
|
pub async fn dispatch_cluster_event(&self, event: ClusterEvent) {
|
|
// Broadcast to channel subscribers
|
|
let _ = self.event_tx.send(event.clone());
|
|
|
|
// Call registered handlers
|
|
match &event {
|
|
ClusterEvent::NodeJoined(node) => {
|
|
for handler in &self.cluster_handlers {
|
|
handler.on_node_joined(node).await;
|
|
}
|
|
}
|
|
ClusterEvent::NodeLeft { node_id, reason } => {
|
|
for handler in &self.cluster_handlers {
|
|
handler.on_node_left(*node_id, *reason).await;
|
|
}
|
|
}
|
|
ClusterEvent::LeaderChanged { old, new } => {
|
|
for handler in &self.cluster_handlers {
|
|
handler.on_leader_changed(*old, *new).await;
|
|
}
|
|
}
|
|
ClusterEvent::BecameLeader => {
|
|
for handler in &self.cluster_handlers {
|
|
handler.on_became_leader().await;
|
|
}
|
|
}
|
|
ClusterEvent::LostLeadership => {
|
|
for handler in &self.cluster_handlers {
|
|
handler.on_lost_leadership().await;
|
|
}
|
|
}
|
|
ClusterEvent::MembershipChanged(members) => {
|
|
for handler in &self.cluster_handlers {
|
|
handler.on_membership_changed(members).await;
|
|
}
|
|
}
|
|
ClusterEvent::PartitionDetected {
|
|
reachable,
|
|
unreachable,
|
|
} => {
|
|
for handler in &self.cluster_handlers {
|
|
handler.on_partition_detected(reachable, unreachable).await;
|
|
}
|
|
}
|
|
ClusterEvent::ClusterReady => {
|
|
for handler in &self.cluster_handlers {
|
|
handler.on_cluster_ready().await;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Dispatch a KV event to all handlers
|
|
pub async fn dispatch_kv_event(&self, event: KvEvent) {
|
|
match &event {
|
|
KvEvent::KeyChanged {
|
|
namespace,
|
|
key,
|
|
value,
|
|
revision,
|
|
} => {
|
|
for handler in &self.kv_handlers {
|
|
handler
|
|
.on_key_changed(namespace, key, value, *revision)
|
|
.await;
|
|
}
|
|
}
|
|
KvEvent::KeyDeleted {
|
|
namespace,
|
|
key,
|
|
revision,
|
|
} => {
|
|
for handler in &self.kv_handlers {
|
|
handler.on_key_deleted(namespace, key, *revision).await;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for EventDispatcher {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|