From 401d43be6214696cabacea74a38dc6b29cefe2eb Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Thu, 23 Apr 2026 14:56:02 -0500 Subject: [PATCH] refactor: pattern-match LeaderElection init and cluster-status dispatch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - get_cluster_aprs_status: fetch_cluster_status/1 dispatches on the clustering flag — true fans out cluster-wide, false goes straight to the local Aprsme.Is status. - init/1: extract schedule_initial_election/1 with true/false heads. The clustered branch sets up the check-and-backstop timers; the non-clustered branch queues an immediate election. Makes the two startup paths obvious from the function signatures. No behavior change; all 17 LeaderElection tests still pass. --- lib/aprsme/cluster/leader_election.ex | 39 +++++++++++++-------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/lib/aprsme/cluster/leader_election.ex b/lib/aprsme/cluster/leader_election.ex index ccc9454..dc45106 100644 --- a/lib/aprsme/cluster/leader_election.ex +++ b/lib/aprsme/cluster/leader_election.ex @@ -50,33 +50,17 @@ defmodule Aprsme.Cluster.LeaderElection do Returns the status from whichever node has an active connection. """ def get_cluster_aprs_status do - cluster_enabled = Application.get_env(:aprsme, :cluster_enabled, false) - - if cluster_enabled do - get_cluster_wide_status() - else - # Non-clustered mode - just return local status - Aprsme.Is.get_status() - end + fetch_cluster_status(Application.get_env(:aprsme, :cluster_enabled, false)) end + defp fetch_cluster_status(true), do: get_cluster_wide_status() + defp fetch_cluster_status(false), do: Aprsme.Is.get_status() + @impl true def init(_opts) do Logger.info("Starting leader election process") - cluster_enabled = Application.get_env(:aprsme, :cluster_enabled, false) - - if cluster_enabled do - Logger.info("Clustering enabled - waiting for cluster formation before leader election") - # Wait for cluster to form, then check periodically - Process.send_after(self(), :check_cluster_and_elect, 2_000) - # Set a timeout to force election if cluster doesn't form - Process.send_after(self(), :force_election_timeout, @max_cluster_wait) - else - Logger.info("Clustering disabled - proceeding with immediate leader election") - # Non-clustered mode - elect immediately - Process.send_after(self(), :attempt_election, 100) - end + schedule_initial_election(cluster_enabled) # Schedule periodic checks Process.send_after(self(), :check_leadership, @check_interval) @@ -87,6 +71,19 @@ defmodule Aprsme.Cluster.LeaderElection do {:ok, %__MODULE__{cluster_enabled: cluster_enabled}} end + # Clustered mode: wait for formation, then elect; schedule a backstop timeout. + defp schedule_initial_election(true) do + Logger.info("Clustering enabled - waiting for cluster formation before leader election") + Process.send_after(self(), :check_cluster_and_elect, 2_000) + Process.send_after(self(), :force_election_timeout, @max_cluster_wait) + end + + # Non-clustered mode: elect immediately. + defp schedule_initial_election(false) do + Logger.info("Clustering disabled - proceeding with immediate leader election") + Process.send_after(self(), :attempt_election, 100) + end + @impl true def handle_info(:check_cluster_and_elect, state) do # Don't keep checking if election was already forced