gemstone_utils.election

SQL-backed leader election with leases and namespaces.

class gemstone_utils.election.ElectionCandidate(**kwargs)[source]

Bases: GemstoneDB

Registered candidate with heartbeat expiry.

Composite primary key: ns, candidate_id.

candidate_id: Mapped[str]
expires_at: Mapped[datetime]
last_heartbeat_at: Mapped[datetime]
ns: Mapped[str]
class gemstone_utils.election.ElectionLeader(**kwargs)[source]

Bases: GemstoneDB

Per-namespace leader lease row.

Primary key: ns. At most one leader per namespace.

leader_id: Mapped[str | None]
lease_expires_at: Mapped[datetime | None]
ns: Mapped[str]
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.

Parameters:
  • candidate_id (UUID) – Process identity UUID attempting election.

  • ns (str | None) – Namespace (default "default").

  • session (Session | None) – Optional shared SQLAlchemy session.

Returns:

UUID of the leader for the namespace after this call.

Return type:

UUID

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.

Parameters:
  • candidate_id (UUID) – Process identity UUID.

  • ns (str | None) – Namespace (default "default").

  • session (Session | None) – Optional shared SQLAlchemy session.

Return type:

None

gemstone_utils.election.is_leader(candidate_id, ns=None, *, session=None)[source]

Return whether candidate_id holds an unexpired leader lease.

Parameters:
  • candidate_id (UUID) – Process identity UUID.

  • ns (str | None) – Namespace (default "default").

  • session (Session | None) – Optional shared SQLAlchemy session.

Returns:

True if this candidate is leader with lease_expires_at > now.

Return type:

bool

gemstone_utils.election.list_candidates(ns=None, *, session=None)[source]

List active candidates (expires_at > now).

Parameters:
  • ns (str | None) – Namespace (default "default").

  • session (Session | None) – Optional shared SQLAlchemy session.

Returns:

Sorted list of candidate UUIDs.

Return type:

list[UUID]

gemstone_utils.election.register_candidate(candidate_id, ns=None, *, session=None)[source]

Register or refresh a candidate in an election namespace.

Parameters:
  • candidate_id (UUID) – Process identity UUID.

  • ns (str | None) – Namespace (default "default").

  • session (Session | None) – Optional shared SQLAlchemy session.

Return type:

None

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 sec is not a positive integer.

Return type:

None

gemstone_utils.election.unregister_candidate(candidate_id, ns=None, *, session=None)[source]

Remove a candidate and clear leadership if it was leader.

Parameters:
  • candidate_id (UUID) – Process identity UUID.

  • ns (str | None) – Namespace (default "default").

  • session (Session | None) – Optional shared SQLAlchemy session.

Return type:

None