Reduce cyclomatic complexity in clustering, encoding, and leader_election
Simplify complex functions to improve readability and maintainability: - clustering.ex: Convert case statement to map lookup for cluster radii - encoding.ex: Extract codepoint validation into separate function clauses - leader_election.ex: Extract PID liveness checking and cleanup logic into helpers Co-Authored-By: Graham <noreply@anthropic.com>
This commit is contained in:
parent
48be64583a
commit
d48a3a291f
3 changed files with 69 additions and 70 deletions
|
|
@ -186,53 +186,53 @@ defmodule Aprsme.Cluster.LeaderElection do
|
||||||
defp cleanup_stale_registrations do
|
defp cleanup_stale_registrations do
|
||||||
case :global.whereis_name(@election_key) do
|
case :global.whereis_name(@election_key) do
|
||||||
:undefined ->
|
:undefined ->
|
||||||
# No registration exists
|
|
||||||
:ok
|
:ok
|
||||||
|
|
||||||
pid when is_pid(pid) ->
|
pid when is_pid(pid) ->
|
||||||
pid_node = node(pid)
|
check_and_cleanup_registration(pid)
|
||||||
connected_nodes = [node() | Node.list()]
|
|
||||||
|
|
||||||
# Check if the PID's node is still connected
|
|
||||||
if pid_node in connected_nodes do
|
|
||||||
# Node is connected, try to check if process is alive
|
|
||||||
try do
|
|
||||||
if pid_node == node() do
|
|
||||||
# Local PID - use Process.alive?
|
|
||||||
if Process.alive?(pid) do
|
|
||||||
:ok
|
|
||||||
else
|
|
||||||
Logger.info("Cleaning up stale leader registration for dead local process #{inspect(pid)}")
|
|
||||||
:global.unregister_name(@election_key)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
# Remote PID - use RPC to check if alive
|
|
||||||
case :rpc.call(pid_node, Process, :alive?, [pid]) do
|
|
||||||
true ->
|
|
||||||
:ok
|
|
||||||
|
|
||||||
false ->
|
|
||||||
Logger.info("Cleaning up stale leader registration for dead remote process #{inspect(pid)}")
|
|
||||||
:global.unregister_name(@election_key)
|
|
||||||
|
|
||||||
{:badrpc, _reason} ->
|
|
||||||
Logger.info("Cleaning up stale leader registration for unreachable process #{inspect(pid)}")
|
|
||||||
:global.unregister_name(@election_key)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
rescue
|
|
||||||
_error ->
|
|
||||||
Logger.info("Cleaning up stale leader registration for problematic process #{inspect(pid)}")
|
|
||||||
:global.unregister_name(@election_key)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
# Node is disconnected - clean up the registration
|
|
||||||
Logger.info("Cleaning up stale leader registration for disconnected node #{pid_node}")
|
|
||||||
:global.unregister_name(@election_key)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp check_and_cleanup_registration(pid) do
|
||||||
|
pid_node = node(pid)
|
||||||
|
connected_nodes = [node() | Node.list()]
|
||||||
|
|
||||||
|
if pid_node in connected_nodes do
|
||||||
|
check_pid_liveness(pid, pid_node)
|
||||||
|
else
|
||||||
|
cleanup_registration("disconnected node #{pid_node}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp check_pid_liveness(pid, pid_node) do
|
||||||
|
if is_pid_alive?(pid, pid_node) do
|
||||||
|
:ok
|
||||||
|
else
|
||||||
|
reason = if pid_node == node(), do: "dead local process", else: "dead remote process"
|
||||||
|
cleanup_registration("#{reason} #{inspect(pid)}")
|
||||||
|
end
|
||||||
|
rescue
|
||||||
|
_error ->
|
||||||
|
cleanup_registration("problematic process #{inspect(pid)}")
|
||||||
|
end
|
||||||
|
|
||||||
|
defp is_pid_alive?(pid, pid_node) when pid_node == node() do
|
||||||
|
Process.alive?(pid)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp is_pid_alive?(pid, pid_node) do
|
||||||
|
if :rpc.call(pid_node, Process, :alive?, [pid]) do
|
||||||
|
true
|
||||||
|
else
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp cleanup_registration(reason) do
|
||||||
|
Logger.info("Cleaning up stale leader registration for #{reason}")
|
||||||
|
:global.unregister_name(@election_key)
|
||||||
|
end
|
||||||
|
|
||||||
defp get_cluster_wide_status do
|
defp get_cluster_wide_status do
|
||||||
all_nodes = [node() | Node.list()]
|
all_nodes = [node() | Node.list()]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -155,25 +155,21 @@ defmodule Aprsme.Encoding do
|
||||||
@spec valid_grapheme?(String.grapheme()) :: boolean()
|
@spec valid_grapheme?(String.grapheme()) :: boolean()
|
||||||
defp valid_grapheme?(grapheme) do
|
defp valid_grapheme?(grapheme) do
|
||||||
case String.to_charlist(grapheme) do
|
case String.to_charlist(grapheme) do
|
||||||
[cp] ->
|
[cp] -> valid_codepoint?(cp)
|
||||||
# Allow tab (0x09), newline (0x0A), carriage return (0x0D)
|
_ -> true
|
||||||
# Remove other control characters
|
|
||||||
case cp do
|
|
||||||
9 -> true
|
|
||||||
10 -> true
|
|
||||||
13 -> true
|
|
||||||
c when c >= 0 and c <= 31 -> false
|
|
||||||
127 -> false
|
|
||||||
c when c >= 128 and c <= 159 -> false
|
|
||||||
_ -> true
|
|
||||||
end
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
# Multi-codepoint grapheme, keep it
|
|
||||||
true
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Allow tab (0x09), newline (0x0A), carriage return (0x0D)
|
||||||
|
# Remove other control characters
|
||||||
|
defp valid_codepoint?(9), do: true
|
||||||
|
defp valid_codepoint?(10), do: true
|
||||||
|
defp valid_codepoint?(13), do: true
|
||||||
|
defp valid_codepoint?(127), do: false
|
||||||
|
defp valid_codepoint?(c) when c >= 0 and c <= 31, do: false
|
||||||
|
defp valid_codepoint?(c) when c >= 128 and c <= 159, do: false
|
||||||
|
defp valid_codepoint?(_), do: true
|
||||||
|
|
||||||
@spec find_invalid_byte_position(binary()) :: non_neg_integer() | nil
|
@spec find_invalid_byte_position(binary()) :: non_neg_integer() | nil
|
||||||
defp find_invalid_byte_position(input) do
|
defp find_invalid_byte_position(input) do
|
||||||
input
|
input
|
||||||
|
|
|
||||||
|
|
@ -46,21 +46,24 @@ defmodule Aprsme.Packets.Clustering do
|
||||||
Calculates the clustering radius in degrees based on zoom level.
|
Calculates the clustering radius in degrees based on zoom level.
|
||||||
Lower zoom levels get larger radii for more aggressive clustering.
|
Lower zoom levels get larger radii for more aggressive clustering.
|
||||||
"""
|
"""
|
||||||
|
# Clustering radius lookup table by zoom level
|
||||||
|
# More aggressive scaling for better separation at higher zooms
|
||||||
|
# Zoom 1: ~5 degrees, Zoom 5: ~0.3 degrees, Zoom 8: ~0.04 degrees
|
||||||
|
@cluster_radii %{
|
||||||
|
1 => 5.0,
|
||||||
|
2 => 2.5,
|
||||||
|
3 => 1.25,
|
||||||
|
4 => 0.625,
|
||||||
|
5 => 0.3125,
|
||||||
|
6 => 0.15625,
|
||||||
|
7 => 0.078125,
|
||||||
|
8 => 0.0390625
|
||||||
|
}
|
||||||
|
@default_radius 0.0390625
|
||||||
|
|
||||||
@spec calculate_cluster_radius(integer()) :: float()
|
@spec calculate_cluster_radius(integer()) :: float()
|
||||||
def calculate_cluster_radius(zoom) do
|
def calculate_cluster_radius(zoom) do
|
||||||
# More aggressive scaling for better separation at higher zooms
|
Map.get(@cluster_radii, zoom, @default_radius)
|
||||||
# Zoom 1: ~5 degrees, Zoom 5: ~0.3 degrees, Zoom 8: ~0.04 degrees
|
|
||||||
case zoom do
|
|
||||||
1 -> 5.0
|
|
||||||
2 -> 2.5
|
|
||||||
3 -> 1.25
|
|
||||||
4 -> 0.625
|
|
||||||
5 -> 0.3125
|
|
||||||
6 -> 0.15625
|
|
||||||
7 -> 0.078125
|
|
||||||
8 -> 0.0390625
|
|
||||||
_ -> 0.0390625
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Filter packets with valid lat/lon coordinates
|
# Filter packets with valid lat/lon coordinates
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue