gemstone_utils.election¶
SQL-backed leader election with leases and namespaces.
- class gemstone_utils.election.ElectionCandidate(**kwargs)[source]¶
Bases:
GemstoneDBRegistered candidate with heartbeat expiry.
Composite primary key:
ns,candidate_id.- expires_at: Mapped[datetime]¶
- last_heartbeat_at: Mapped[datetime]¶
- class gemstone_utils.election.ElectionLeader(**kwargs)[source]¶
Bases:
GemstoneDBPer-namespace leader lease row.
Primary key:
ns. At most one leader per namespace.- updated_at: Mapped[datetime]¶
- gemstone_utils.election.elect(candidate_id, ns=None, *, session=None)[source]¶
Acquire or renew leadership and return the current leader UUID.
Leadership is taken when vacant, expired, or already held by the caller. Does not preempt another candidate with an unexpired lease.
- gemstone_utils.election.heartbeat(candidate_id, ns=None, *, session=None)[source]¶
Refresh candidate heartbeat and extend expiry.
Equivalent to
register_candidate()when the row already exists.
- gemstone_utils.election.is_leader(candidate_id, ns=None, *, session=None)[source]¶
Return whether
candidate_idholds an unexpired leader lease.
- gemstone_utils.election.list_candidates(ns=None, *, session=None)[source]¶
List active candidates (
expires_at > now).
- gemstone_utils.election.register_candidate(candidate_id, ns=None, *, session=None)[source]¶
Register or refresh a candidate in an election namespace.
- gemstone_utils.election.set_expire(sec)[source]¶
Set the candidate and leader lease window in seconds.
Call once at startup. Default is 60 seconds.
- Parameters:
sec (int) – Positive lease duration in seconds.
- Raises:
ValueError – If
secis not a positive integer.- Return type:
None