apeters 1d204f26b8 pre-Korves.Net
Signed-off-by: apeters <apeters@korves.net>
2025-05-21 08:05:07 +00:00

61 lines
1.9 KiB
Python

from components.logs import logger
from components.models.cluster import Role
def elect_leader(peers: "Peers") -> None:
def _destroy():
peers.local.leader = None
peers.local.role = Role.FOLLOWER
peers.local.swarm = ""
n_eligible_peers = len(peers.get_established(include_local=True))
n_all_peers = len(peers.remotes) + 1 # + self
if not (n_eligible_peers >= (51 / 100) * n_all_peers):
logger.info("Cannot elect leader node, not enough peers")
_destroy()
return
leader, started = min(
(
(peer, peer_data.started)
for peer, peer_data in peers.remotes.items()
if peer_data._fully_established
),
key=lambda x: x[1],
default=(None, float("inf")),
)
if peers.local.started < started:
if peers.local.leader != peers.local.name:
logger.info("This node has been elected as the leader.")
peers.local.leader = peers.local.name
peers.local.role = Role.LEADER
else:
if peers.remotes[leader].leader == "?CONFUSED":
_destroy()
logger.info(
f"""Potential leader node '{leader}' is still in the
election process or confused; waiting."""
)
return
if peers.remotes[leader].leader != leader:
_destroy()
logger.warning(
f"Potential leader node '{leader}' reports a different leader; waiting"
)
return
if peers.local.leader != leader:
peers.local.leader = leader
peers.local.role = Role.FOLLOWER
logger.info(f"Elected node '{leader}' as the leader")
if peers.local.leader:
peers.local.swarm = ";".join(peers.get_established(include_local=True))
peers.local.swarm_complete = n_eligible_peers == n_all_peers
logger.debug(f"Cluster size {n_eligible_peers}/{n_all_peers}")