LeaderElection

Struct LeaderElection 

Source
pub struct LeaderElection { /* private fields */ }
Expand description

Coordinator for distributed leader election.

LeaderElection provides the interface for participating in leader elections backed by FoundationDB. Multiple independent elections can coexist by using different Subspaces.

§Lifecycle

┌─────────────────────────────────────────────────────────────────┐
│  1. new()              Create instance with subspace            │
│  2. initialize()       Set up election (once globally)          │
│  3. register_candidate() Join as candidate (once per process)   │
│  4. run_election_cycle()  Main loop (every heartbeat_interval)  │
│  5. resign_leadership() + unregister_candidate()  Cleanup       │
└─────────────────────────────────────────────────────────────────┘

§Methods by Category

§Setup

§Candidate Management

§Leadership Operations (O(1))

§High-Level API

§Configuration

§Thread Safety

LeaderElection is Clone, Send, and Sync. It holds only a Subspace and can be safely shared across tasks. Each method operates within the provided transaction’s scope.

§See Also

See the module documentation for algorithm details, key concepts (ballots, leases, preemption), and configuration guidelines.

Implementations§

Source§

impl LeaderElection

Source

pub fn new(subspace: Subspace) -> Self

Create a new leader election instance with the given subspace

The subspace isolates this election from others in the database. All election data will be stored under this subspace prefix.

§Arguments
  • subspace - The FoundationDB subspace to use for storing election data
Source

pub async fn initialize<T>(&self, txn: &T) -> Result<()>
where T: Deref<Target = Transaction>,

Initialize the leader election system with default settings

This must be called once before any processes can participate in the election. Sets up the necessary configuration with sensible defaults:

  • 10 second lease duration
  • 3 second heartbeat interval
  • 15 second candidate timeout
  • Elections enabled
  • Preemption enabled

This operation is idempotent - calling it multiple times has no effect.

Source

pub async fn initialize_with_config<T>( &self, txn: &T, config: ElectionConfig, ) -> Result<()>
where T: Deref<Target = Transaction>,

Initialize the leader election system with custom configuration

Allows fine-tuning election parameters for specific use cases. This must be called once before any processes can participate.

§Arguments
  • config - Custom election configuration
Source

pub async fn write_config<T>( &self, txn: &T, config: &ElectionConfig, ) -> Result<()>
where T: Deref<Target = Transaction>,

Write election configuration

Updates the global election parameters dynamically.

§Warning

Changing configuration during active elections may cause temporary leadership instability.

Source

pub async fn read_config<T>(&self, txn: &T) -> Result<ElectionConfig>
where T: Deref<Target = Transaction>,

Read current election configuration

Source

pub async fn register_candidate<T>( &self, txn: &T, process_id: &str, priority: i32, current_time: Duration, ) -> Result<()>
where T: Deref<Target = Transaction>,

Register as a candidate

Registers this process as a candidate for leadership. Uses SetVersionstampedValue to assign a unique versionstamp at registration time.

§Arguments
  • process_id - Unique identifier for this process
  • priority - Priority level (higher = more preferred for leadership)
  • current_time - Current time for heartbeat timestamp
§Note

The versionstamp is assigned once at registration and preserved on heartbeats. You’ll need to read the candidate info after commit to get the actual versionstamp.

Source

pub async fn heartbeat_candidate<T>( &self, txn: &T, process_id: &str, priority: i32, current_time: Duration, ) -> Result<()>
where T: Deref<Target = Transaction>,

Send heartbeat as candidate

Updates the candidate’s timestamp to indicate liveness. This should be called periodically (at heartbeat_interval).

§Arguments
  • process_id - Unique identifier for this process
  • priority - Priority level (can be updated on each heartbeat)
  • current_time - Current time for heartbeat timestamp
§Errors

Returns ProcessNotFound if not registered

Source

pub async fn unregister_candidate<T>( &self, txn: &T, process_id: &str, ) -> Result<()>
where T: Deref<Target = Transaction>,

Unregister as candidate

Removes this process from the candidate list. If leader, call resign_leadership first.

Source

pub async fn get_candidate<T>( &self, txn: &T, process_id: &str, ) -> Result<Option<CandidateInfo>>
where T: Deref<Target = Transaction>,

Get candidate info for a specific process

Source

pub async fn list_candidates<T>( &self, txn: &T, current_time: Duration, ) -> Result<Vec<CandidateInfo>>
where T: Deref<Target = Transaction>,

List all alive candidates

O(N) operation - use sparingly, mainly for monitoring.

Source

pub async fn evict_dead_candidates<T>( &self, txn: &T, current_time: Duration, ) -> Result<usize>
where T: Deref<Target = Transaction>,

Remove dead candidates

O(N) operation - should be called by leader periodically. Returns count of evicted candidates.

Source

pub async fn try_claim_leadership<T>( &self, txn: &T, process_id: &str, priority: i32, current_time: Duration, ) -> Result<Option<LeaderState>>
where T: Deref<Target = Transaction>,

Try to claim leadership

Attempts to become the leader. This is an O(1) operation that:

  1. Looks up candidate registration to get versionstamp
  2. Reads the current leader state
  3. Checks if we can claim (no leader, expired lease, or preemption)
  4. Writes new leader state with incremented ballot
§Arguments
  • process_id - Unique identifier for this process
  • priority - Priority level for preemption decisions
  • current_time - Current time for lease calculation
§Returns
  • Ok(Some(state)) - Successfully claimed leadership
  • Ok(None) - Cannot claim, another valid leader exists
  • Err(UnregisteredCandidate) - Process is not registered as a candidate
Source

pub async fn refresh_lease<T>( &self, txn: &T, process_id: &str, current_time: Duration, ) -> Result<Option<LeaderState>>
where T: Deref<Target = Transaction>,

Refresh leadership lease

Called periodically by the leader to extend lease. Fails if no longer the leader.

§Returns
  • Ok(Some(state)) - Lease refreshed
  • Ok(None) - No longer the leader
Source

pub async fn resign_leadership<T>( &self, txn: &T, process_id: &str, ) -> Result<bool>
where T: Deref<Target = Transaction>,

Voluntarily resign leadership

Immediately releases leadership.

§Returns

true if was leader and resigned, false otherwise

Source

pub async fn is_leader<T>( &self, txn: &T, process_id: &str, current_time: Duration, ) -> Result<bool>
where T: Deref<Target = Transaction>,

Check if this process is the current leader

O(1) operation.

Source

pub async fn get_leader<T>( &self, txn: &T, current_time: Duration, ) -> Result<Option<LeaderState>>
where T: Deref<Target = Transaction>,

Get current leader information

O(1) operation. Returns None if no leader or lease expired.

Source

pub async fn get_leader_raw<T>(&self, txn: &T) -> Result<Option<LeaderState>>
where T: Deref<Target = Transaction>,

Get current leader information without lease validation

O(1) operation. Returns leader state regardless of whether lease has expired. Useful for debugging, monitoring, and invariant checking.

Source

pub async fn run_election_cycle<T>( &self, txn: &T, process_id: &str, priority: i32, current_time: Duration, ) -> Result<ElectionResult>
where T: Deref<Target = Transaction>,

Run a complete election cycle

Combines candidate heartbeat + leadership claim in one operation. This is what most users should call in their main loop.

§Arguments
  • process_id - Unique identifier for this process
  • priority - Priority level
  • current_time - Current time
§Returns

ElectionResult::Leader if this process is leader, ElectionResult::Follower otherwise

Trait Implementations§

Source§

impl Clone for LeaderElection

Source§

fn clone(&self) -> LeaderElection

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

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

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V