ReplicationCore

Trait ReplicationCore 

Source
pub trait ReplicationCore<T>:
    Send
    + Sync
    + 'static
where T: TypeConfig,
{ // Required methods fn handle_raft_request_in_batch<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, entry_payloads: Vec<EntryPayload>, state_snapshot: StateSnapshot, leader_state_snapshot: LeaderStateSnapshot, cluster_metadata: &'life1 ClusterMetadata, ctx: &'life2 RaftContext<T>, ) -> Pin<Box<dyn Future<Output = Result<AppendResults>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait; fn handle_success_response( &self, peer_id: u32, peer_term: u64, success_result: SuccessResult, leader_term: u64, ) -> Result<PeerUpdate>; fn handle_conflict_response( &self, peer_id: u32, conflict_result: ConflictResult, raft_log: &Arc<ROF<T>>, current_next_index: u64, ) -> Result<PeerUpdate>; fn if_update_commit_index_as_follower( my_commit_index: u64, last_raft_log_id: u64, leader_commit_index: u64, ) -> Option<u64>; fn retrieve_to_be_synced_logs_for_peers( &self, new_entries: Vec<Entry>, leader_last_index_before_inserting_new_entries: u64, max_legacy_entries_per_peer: u64, peer_next_indices: &HashMap<u32, u64>, raft_log: &Arc<ROF<T>>, ) -> DashMap<u32, Vec<Entry>>; fn handle_append_entries<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, request: AppendEntriesRequest, state_snapshot: &'life1 StateSnapshot, raft_log: &'life2 Arc<ROF<T>>, ) -> Pin<Box<dyn Future<Output = Result<AppendResponseWithUpdates>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait; fn check_append_entries_request_is_legal( &self, my_term: u64, request: &AppendEntriesRequest, raft_log: &Arc<ROF<T>>, ) -> AppendEntriesResponse; }
Expand description

Core replication protocol operations

Required Methods§

Source

fn handle_raft_request_in_batch<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, entry_payloads: Vec<EntryPayload>, state_snapshot: StateSnapshot, leader_state_snapshot: LeaderStateSnapshot, cluster_metadata: &'life1 ClusterMetadata, ctx: &'life2 RaftContext<T>, ) -> Pin<Box<dyn Future<Output = Result<AppendResults>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

As Leader, send replications to peers (combines regular heartbeats and client proposals).

Performs peer synchronization checks:

  1. Verifies if any peer’s next_id <= leader’s commit_index
  2. For non-synced peers: retrieves unsynced logs and buffers them
  3. Prepends unsynced entries to the entries queue
§Returns
  • Ok(AppendResults) with aggregated replication outcomes
  • Err for unrecoverable errors
§Return Result Semantics
  1. Insufficient Quorum: Returns Ok(AppendResults) with commit_quorum_achieved = false when:

    • Responses received from all nodes but majority acceptance not achieved
    • Partial timeouts reduce successful responses below majority
  2. Timeout Handling:

    • Partial timeouts: Returns Ok with commit_quorum_achieved = false
    • Complete timeout: Returns Ok with commit_quorum_achieved = false
    • Timeout peers are EXCLUDED from peer_updates
  3. Error Conditions: Returns Err ONLY for:

    • Empty voting members (ReplicationError::NoPeerFound)
    • Log generation failures (generate_new_entries errors)
    • Higher term detected in peer response (ReplicationError::HigherTerm)
    • Critical response handling errors
§Guarantees
  • Only peers with successful responses appear in peer_updates
  • Timeouts never cause top-level Err (handled as failed responses)
  • Leader self-vote always counted in quorum calculation
§Note
  • Leader state should be updated by LeaderState only(follows SRP).
§Quorum
  • If there are no voters (not even the leader), quorum is not possible.
  • If the leader is the only voter, quorum is always achieved.
  • If all nodes are learners, quorum is not achieved.
Source

fn handle_success_response( &self, peer_id: u32, peer_term: u64, success_result: SuccessResult, leader_term: u64, ) -> Result<PeerUpdate>

Handles successful AppendEntries responses

Updates peer match/next indices according to:

  • Last matched log index
  • Current leader term
Source

fn handle_conflict_response( &self, peer_id: u32, conflict_result: ConflictResult, raft_log: &Arc<ROF<T>>, current_next_index: u64, ) -> Result<PeerUpdate>

Resolves log conflicts from follower responses

Implements conflict backtracking optimization (Section 5.3)

Source

fn if_update_commit_index_as_follower( my_commit_index: u64, last_raft_log_id: u64, leader_commit_index: u64, ) -> Option<u64>

Determines follower commit index advancement

Applies Leader’s commit index according to:

  • min(leader_commit, last_local_log_index)
Source

fn retrieve_to_be_synced_logs_for_peers( &self, new_entries: Vec<Entry>, leader_last_index_before_inserting_new_entries: u64, max_legacy_entries_per_peer: u64, peer_next_indices: &HashMap<u32, u64>, raft_log: &Arc<ROF<T>>, ) -> DashMap<u32, Vec<Entry>>

Gathers legacy logs for lagging peers

Performs log segmentation based on:

  • Peer’s next_index
  • Max allowed historical entries
Source

fn handle_append_entries<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, request: AppendEntriesRequest, state_snapshot: &'life1 StateSnapshot, raft_log: &'life2 Arc<ROF<T>>, ) -> Pin<Box<dyn Future<Output = Result<AppendResponseWithUpdates>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Handles an incoming AppendEntries RPC request (called by ALL ROLES)

Core responsibilities:

  1. Term validation and comparison (RFC §5.1)
  2. Log consistency checking (prev_log_index/term)
  3. Entry appending with conflict resolution (RFC §5.3)
  4. Commit index advancement (RFC §5.3)
§Critical Architecture Constraints
  1. ROLE AGNOSTIC - This method contains no role-specific logic. It simply:
    • Validates the RPC against local state
    • Returns required state updates
  2. STATE CHANGE ISOLATION - Never directly modifies:
    • Current role (Leader/Follower/etc)
    • Persistent state (term/votedFor)
    • Volatile leader state (nextIndex/matchIndex)
  3. CALLER MUST:
    • Check response.term_update for term conflicts
    • If higher term exists, transition to Follower
    • Apply other state updates via role_tx

Validates an incoming AppendEntries RPC from a Leader against Raft protocol rules.

This function implements the log consistency checks defined in Raft paper Section 5.3. It determines whether to accept the Leader’s log entries by verifying:

  1. Term freshness
  2. Virtual log (prev_log_index=0) handling
  3. Previous log entry consistency
§Raft Protocol Rules Enforced
  1. Term Check (Raft Paper 5.1):
    • Reject requests with stale terms to prevent partitioned Leaders
  2. Virtual Log Handling (Implementation-Specific):
    • Special case for empty logs (prev_log_index=0 && prev_log_term=0)
  3. Log Matching (Raft Paper 5.3):
    • Ensure Leader’s prev_log_index/term matches Follower’s log
§Parameters
  • my_term: Current node’s term
  • request: Leader’s AppendEntries RPC
  • raft_log: Reference to node’s log store
§Return

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§

Source§

impl<T> ReplicationCore<T> for ReplicationHandler<T>
where T: TypeConfig,