fix: handle APRS status DB ownership exits

This commit is contained in:
Graham McIntire 2026-03-22 15:58:14 -05:00
parent 26e86ddba8
commit 8937c1fb57
No known key found for this signature in database
2 changed files with 50 additions and 4 deletions

View file

@ -129,6 +129,7 @@ defmodule Aprsme.Is do
# GenServer is not running (disconnected) # GenServer is not running (disconnected)
server = Application.get_env(:aprsme, :aprs_is_server, nil) server = Application.get_env(:aprsme, :aprs_is_server, nil)
port = Application.get_env(:aprsme, :aprs_is_port, 14_580) port = Application.get_env(:aprsme, :aprs_is_port, 14_580)
{stored_packet_count, oldest_packet_timestamp} = safe_packet_storage_stats()
%{ %{
connected: false, connected: false,
@ -139,8 +140,8 @@ defmodule Aprsme.Is do
login_id: Application.get_env(:aprsme, :aprs_is_login_id, "W5ISP"), login_id: Application.get_env(:aprsme, :aprs_is_login_id, "W5ISP"),
filter: Application.get_env(:aprsme, :aprs_is_default_filter, "r/33/-96/100"), filter: Application.get_env(:aprsme, :aprs_is_default_filter, "r/33/-96/100"),
packet_stats: default_packet_stats(), packet_stats: default_packet_stats(),
stored_packet_count: Aprsme.Packets.get_total_packet_count(), stored_packet_count: stored_packet_count,
oldest_packet_timestamp: Aprsme.Packets.get_oldest_packet_timestamp() oldest_packet_timestamp: oldest_packet_timestamp
} }
_pid -> _pid ->
@ -151,6 +152,7 @@ defmodule Aprsme.Is do
# GenServer exists but not responding # GenServer exists but not responding
server = Application.get_env(:aprsme, :aprs_is_server, ~c"rotate.aprs2.net") server = Application.get_env(:aprsme, :aprs_is_server, ~c"rotate.aprs2.net")
port = Application.get_env(:aprsme, :aprs_is_port, 14_580) port = Application.get_env(:aprsme, :aprs_is_port, 14_580)
{stored_packet_count, oldest_packet_timestamp} = safe_packet_storage_stats()
%{ %{
connected: false, connected: false,
@ -161,13 +163,23 @@ defmodule Aprsme.Is do
login_id: Application.get_env(:aprsme, :aprs_is_login_id, "W5ISP"), login_id: Application.get_env(:aprsme, :aprs_is_login_id, "W5ISP"),
filter: Application.get_env(:aprsme, :aprs_is_default_filter, "r/33/-96/100"), filter: Application.get_env(:aprsme, :aprs_is_default_filter, "r/33/-96/100"),
packet_stats: default_packet_stats(), packet_stats: default_packet_stats(),
stored_packet_count: Aprsme.Packets.get_total_packet_count(), stored_packet_count: stored_packet_count,
oldest_packet_timestamp: Aprsme.Packets.get_oldest_packet_timestamp() oldest_packet_timestamp: oldest_packet_timestamp
} }
end end
end end
end end
defp safe_packet_storage_stats do
{Aprsme.Packets.get_total_packet_count(), Aprsme.Packets.get_oldest_packet_timestamp()}
rescue
DBConnection.OwnershipError ->
{0, nil}
catch
:exit, _ ->
{0, nil}
end
def set_filter(filter_string), do: send_message("#filter #{filter_string}") def set_filter(filter_string), do: send_message("#filter #{filter_string}")
def list_active_filters, do: send_message("#filter?") def list_active_filters, do: send_message("#filter?")

View file

@ -7,6 +7,8 @@ defmodule Aprsme.IsTest do
import ExUnit.CaptureLog import ExUnit.CaptureLog
alias Ecto.Adapters.SQL.Sandbox
# Helper to build a default GenServer state for direct callback testing # Helper to build a default GenServer state for direct callback testing
defp build_state(overrides \\ %{}) do defp build_state(overrides \\ %{}) do
timer = Process.send_after(self(), :noop_timer, to_timeout(minute: 5)) timer = Process.send_after(self(), :noop_timer, to_timeout(minute: 5))
@ -519,6 +521,38 @@ defmodule Aprsme.IsTest do
assert status.login_id == "TEST" assert status.login_id == "TEST"
assert status.filter == "r/33/-96/100" assert status.filter == "r/33/-96/100"
end end
test "returns fallback packet storage stats when called from a non-owner process" do
parent = self()
owner =
spawn(fn ->
:ok = Sandbox.checkout(Aprsme.Repo)
send(parent, :sandbox_owner_ready)
receive do
:stop -> :ok
end
end)
assert_receive :sandbox_owner_ready
task =
Task.async(fn ->
receive do
:query_status -> Aprsme.Is.get_status()
end
end)
Sandbox.allow(Aprsme.Repo, owner, task.pid)
send(owner, :stop)
send(task.pid, :query_status)
status = Task.await(task)
assert status.connected == false
assert status.stored_packet_count == 0
assert status.oldest_packet_timestamp == nil
end
end end
describe "buffer line extraction via TCP data" do describe "buffer line extraction via TCP data" do