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
new- Create election instanceinitialize- Initialize with defaultsinitialize_with_config- Initialize with customElectionConfig
§Candidate Management
register_candidate- Join the electionheartbeat_candidate- Send liveness heartbeatunregister_candidate- Leave the electionget_candidate- Query candidate infolist_candidates- List all alive candidates (O(N))evict_dead_candidates- Remove timed-out candidates (O(N))
§Leadership Operations (O(1))
try_claim_leadership- Attempt to become leaderrefresh_lease- Extend leadership leaseresign_leadership- Voluntarily step downis_leader- Check if this process is leaderget_leader- Get current leader (lease-validated)get_leader_raw- Get current leader (no lease check)
§High-Level API
run_election_cycle- Combined heartbeat + claim (recommended for main loop)
§Configuration
read_config- Read current configurationwrite_config- Update configuration dynamically
§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.
§Related Types
ElectionConfig- Configuration parametersElectionResult- Return type fromrun_election_cycleLeaderState- Leader information including ballot (fencing token)CandidateInfo- Registered candidate informationLeaderElectionError- Error types for this module
§See Also
See the module documentation for algorithm details, key concepts (ballots, leases, preemption), and configuration guidelines.
Implementations§
Source§impl LeaderElection
impl LeaderElection
Sourcepub fn new(subspace: Subspace) -> Self
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
Sourcepub async fn initialize<T>(&self, txn: &T) -> Result<()>where
T: Deref<Target = Transaction>,
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.
Sourcepub async fn initialize_with_config<T>(
&self,
txn: &T,
config: ElectionConfig,
) -> Result<()>where
T: Deref<Target = Transaction>,
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
Sourcepub async fn write_config<T>(
&self,
txn: &T,
config: &ElectionConfig,
) -> Result<()>where
T: Deref<Target = Transaction>,
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.
Sourcepub async fn read_config<T>(&self, txn: &T) -> Result<ElectionConfig>where
T: Deref<Target = Transaction>,
pub async fn read_config<T>(&self, txn: &T) -> Result<ElectionConfig>where
T: Deref<Target = Transaction>,
Read current election configuration
Sourcepub async fn register_candidate<T>(
&self,
txn: &T,
process_id: &str,
priority: i32,
current_time: Duration,
) -> Result<()>where
T: Deref<Target = Transaction>,
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 processpriority- 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.
Sourcepub async fn heartbeat_candidate<T>(
&self,
txn: &T,
process_id: &str,
priority: i32,
current_time: Duration,
) -> Result<()>where
T: Deref<Target = Transaction>,
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 processpriority- Priority level (can be updated on each heartbeat)current_time- Current time for heartbeat timestamp
§Errors
Returns ProcessNotFound if not registered
Sourcepub async fn unregister_candidate<T>(
&self,
txn: &T,
process_id: &str,
) -> Result<()>where
T: Deref<Target = Transaction>,
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.
Sourcepub async fn get_candidate<T>(
&self,
txn: &T,
process_id: &str,
) -> Result<Option<CandidateInfo>>where
T: Deref<Target = Transaction>,
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
Sourcepub async fn list_candidates<T>(
&self,
txn: &T,
current_time: Duration,
) -> Result<Vec<CandidateInfo>>where
T: Deref<Target = Transaction>,
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.
Sourcepub async fn evict_dead_candidates<T>(
&self,
txn: &T,
current_time: Duration,
) -> Result<usize>where
T: Deref<Target = Transaction>,
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.
Sourcepub 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>,
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:
- Looks up candidate registration to get versionstamp
- Reads the current leader state
- Checks if we can claim (no leader, expired lease, or preemption)
- Writes new leader state with incremented ballot
§Arguments
process_id- Unique identifier for this processpriority- Priority level for preemption decisionscurrent_time- Current time for lease calculation
§Returns
Ok(Some(state))- Successfully claimed leadershipOk(None)- Cannot claim, another valid leader existsErr(UnregisteredCandidate)- Process is not registered as a candidate
Sourcepub async fn refresh_lease<T>(
&self,
txn: &T,
process_id: &str,
current_time: Duration,
) -> Result<Option<LeaderState>>where
T: Deref<Target = Transaction>,
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 refreshedOk(None)- No longer the leader
Sourcepub async fn resign_leadership<T>(
&self,
txn: &T,
process_id: &str,
) -> Result<bool>where
T: Deref<Target = Transaction>,
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
Sourcepub async fn is_leader<T>(
&self,
txn: &T,
process_id: &str,
current_time: Duration,
) -> Result<bool>where
T: Deref<Target = Transaction>,
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.
Sourcepub async fn get_leader<T>(
&self,
txn: &T,
current_time: Duration,
) -> Result<Option<LeaderState>>where
T: Deref<Target = Transaction>,
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.
Sourcepub async fn get_leader_raw<T>(&self, txn: &T) -> Result<Option<LeaderState>>where
T: Deref<Target = Transaction>,
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.
Sourcepub async fn run_election_cycle<T>(
&self,
txn: &T,
process_id: &str,
priority: i32,
current_time: Duration,
) -> Result<ElectionResult>where
T: Deref<Target = Transaction>,
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 processpriority- Priority levelcurrent_time- Current time
§Returns
ElectionResult::Leader if this process is leader, ElectionResult::Follower otherwise
Trait Implementations§
Source§impl Clone for LeaderElection
impl Clone for LeaderElection
Source§fn clone(&self) -> LeaderElection
fn clone(&self) -> LeaderElection
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more