MockReplicationCore

Struct MockReplicationCore 

Source
pub struct MockReplicationCore<T>
where T: TypeConfig,
{ /* private fields */ }
Expand description

Core replication protocol operations

Implementations§

Source§

impl<T> MockReplicationCore<T>
where T: TypeConfig,

Source

pub fn checkpoint(&mut self)

Validate that all current expectations for all methods have been satisfied, and discard them.

Source

pub fn new() -> Self

Create a new mock object with no expectations.

This method will not be generated if the real struct already has a new method. However, it will be generated if the struct implements a trait with a new method. The trait’s new method can still be called like <MockX as TraitY>::new

Source§

impl<T> MockReplicationCore<T>
where T: TypeConfig,

Source

pub fn expect_handle_raft_request_in_batch(&mut self) -> &mut Expectation<T>

Create an Expectation for mocking the handle_raft_request_in_batch method

Source

pub fn expect_handle_success_response(&mut self) -> &mut Expectation<T>

Create an Expectation for mocking the handle_success_response method

Source

pub fn expect_handle_conflict_response(&mut self) -> &mut Expectation<T>

Create an Expectation for mocking the handle_conflict_response method

Source

pub fn expect_retrieve_to_be_synced_logs_for_peers( &mut self, ) -> &mut Expectation<T>

Create an Expectation for mocking the retrieve_to_be_synced_logs_for_peers method

Source

pub fn expect_handle_append_entries(&mut self) -> &mut Expectation<T>

Create an Expectation for mocking the handle_append_entries method

Create an Expectation for mocking the check_append_entries_request_is_legal method

Source

pub fn if_update_commit_index_as_follower_context() -> Context<T>

Create a Context for mocking the if_update_commit_index_as_follower method

Trait Implementations§

Source§

impl<T> Debug for MockReplicationCore<T>
where T: TypeConfig,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl<T> Default for MockReplicationCore<T>
where T: TypeConfig,

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

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

Core replication protocol operations

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

Auto Trait Implementations§

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> Any for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Source§

fn type_name(&self) -> &'static str

Source§

impl<T> AnySync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync>

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> IntoRequest<T> for T

Source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
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