noleader
A small, ergonomic Rust crate for leader election using NATS KeyValue (KV) as the distributed locking mechanism. Does not require a fixed set of nodes—any number of candidates can join or drop out dynamically.
Disclaimer
This library is still young and the API is subject to change.
Features
- Distributed locking with TTL Uses NATS JetStream KV store to create a key with a TTL, ensuring only one leader at a time.
- Automatic renewal with jitter Renews leadership every ~10 s (plus a random back-off) to avoid thundering‐herd elections.
- Graceful shutdown
Integrates with
tokio_util::sync::CancellationTokenso you can cancel leadership and ongoing work cleanly. - Leader-only work loop
do_while_leaderruns your async closure as long as you hold leadership, cancelling it immediately upon relinquish. - No required cluster size Nodes can join or leave at any time—no minimum/maximum constraints.
Intended use-case
Noleader is not built for distributed consensus, or fast re-election produces. It take upwards to a minute to get reelected, state is the users responsibility to handle.
Noleader is pretty much just a distributed lock, intended for use-cases where the use wants to only have a single node scheduling work etc.
Good alternatives are:
- Raft (for distributed consensus)
- Relational databases (for locking)
Installation
[]
= "0.1"
Then in your code:
use Leader;
Quick Example
use CancellationToken;
use EnvFilter;
async
API Overview
Leader::new(bucket: &str, key: &str, client: async_nats::Client) -> LeaderCreate a new election participant.create_bucket(&self) -> anyhow::Result<()>Ensures the KV bucket exists (no-op if already created).start(&self, token: CancellationToken) -> anyhow::Result<()>Begins the background leader-election loop; renews TTL on success or retries on failure.do_while_leader<F, Fut>(&self, f: F) -> anyhow::Result<()>Runs your closure as long as you hold leadership; cancels immediately on loss.leader_id(&self) -> UuidReturns your unique candidate ID.is_leader(&self) -> StatusReturnsStatus::LeaderorStatus::Candidate, taking shutdown into account.
Types
License
This crate is licensed under the same terms as the workspace (MIT or Apache-2.0). See LICENSE-MIT and LICENSE-APACHE.
Contribute
Issues and PRs are welcome!
Repository: https://git.front.kjuulh.io/kjuulh/noleader
Development happens publicly on the main branch—feel free to fork and send a merge request.