aprs.me/test/aprsme/packets/prepared_queries_test.exs
Graham McIntire 84e65232e5
Batch RF path queries, batch marker removals, and JS callsign index
- Replace N+1 get_latest_packet_for_callsign calls in RF path loading
  with single get_latest_packets_for_callsigns batch query (DISTINCT ON)
- Change batch packet processing to collect marker removal IDs and push
  one remove_markers_batch event instead of individual remove_marker calls
- Add callsignIndex reverse map (callsign_group → Set<markerID>) for O(1)
  lookup in new_packet/new_packets handlers instead of scanning all markers
2026-02-20 09:04:22 -06:00

189 lines
5.5 KiB
Elixir

defmodule Aprsme.Packets.PreparedQueriesTest do
use Aprsme.DataCase, async: false
alias Aprsme.Packet
alias Aprsme.Packets.PreparedQueries
alias Aprsme.Repo
defp create_positioned_packet(attrs) do
defaults = %{
sender: "TEST-1",
base_callsign: "TEST",
ssid: "1",
destination: "APRS",
data_type: "position",
lat: Decimal.new("33.0000"),
lon: Decimal.new("-96.0000"),
received_at: DateTime.truncate(DateTime.utc_now(), :second)
}
merged = Map.merge(defaults, attrs)
%Packet{}
|> Packet.changeset(Map.from_struct(Map.merge(%Packet{}, merged)))
|> Repo.insert()
end
describe "get_latest_packets_for_callsigns/1" do
test "returns full packet structs for multiple callsigns" do
{:ok, _} =
create_positioned_packet(%{
sender: "K5GVL-10",
base_callsign: "K5GVL",
ssid: "10",
lat: Decimal.new("33.1000"),
lon: Decimal.new("-96.6000"),
comment: "Digi TX"
})
{:ok, _} =
create_positioned_packet(%{
sender: "N5TXZ-10",
base_callsign: "N5TXZ",
ssid: "10",
lat: Decimal.new("33.2000"),
lon: Decimal.new("-96.5000"),
comment: "iGate"
})
result = PreparedQueries.get_latest_packets_for_callsigns(["K5GVL-10", "N5TXZ-10"])
assert length(result) == 2
assert Enum.all?(result, &is_struct(&1, Packet))
senders = Enum.map(result, & &1.sender)
assert "K5GVL-10" in senders
assert "N5TXZ-10" in senders
k5gvl = Enum.find(result, &(&1.sender == "K5GVL-10"))
assert_in_delta k5gvl.lat, 33.1, 0.01
assert_in_delta k5gvl.lon, -96.6, 0.01
end
test "returns empty list for empty input" do
assert PreparedQueries.get_latest_packets_for_callsigns([]) == []
end
test "returns empty list for nonexistent callsigns" do
result = PreparedQueries.get_latest_packets_for_callsigns(["NONEXIST-1", "FAKE-2"])
assert result == []
end
test "returns latest packet when multiple exist for a callsign" do
{:ok, _} =
create_positioned_packet(%{
sender: "K5GVL-10",
base_callsign: "K5GVL",
ssid: "10",
lat: Decimal.new("33.1000"),
lon: Decimal.new("-96.6000"),
received_at: DateTime.add(DateTime.utc_now(), -3600, :second)
})
{:ok, _} =
create_positioned_packet(%{
sender: "K5GVL-10",
base_callsign: "K5GVL",
ssid: "10",
lat: Decimal.new("34.0000"),
lon: Decimal.new("-97.0000"),
received_at: DateTime.truncate(DateTime.utc_now(), :second)
})
result = PreparedQueries.get_latest_packets_for_callsigns(["K5GVL-10"])
assert length(result) == 1
packet = hd(result)
assert is_struct(packet, Packet)
assert_in_delta packet.lat, 34.0, 0.01
assert_in_delta packet.lon, -97.0, 0.01
end
end
describe "get_latest_positions_for_callsigns/1" do
test "returns positions for multiple callsigns" do
{:ok, _} =
create_positioned_packet(%{
sender: "K5GVL-10",
base_callsign: "K5GVL",
ssid: "10",
lat: Decimal.new("33.1000"),
lon: Decimal.new("-96.6000")
})
{:ok, _} =
create_positioned_packet(%{
sender: "N5TXZ-10",
base_callsign: "N5TXZ",
ssid: "10",
lat: Decimal.new("33.2000"),
lon: Decimal.new("-96.5000")
})
result = PreparedQueries.get_latest_positions_for_callsigns(["K5GVL-10", "N5TXZ-10"])
assert length(result) == 2
callsigns = Enum.map(result, & &1.callsign)
assert "K5GVL-10" in callsigns
assert "N5TXZ-10" in callsigns
k5gvl = Enum.find(result, &(&1.callsign == "K5GVL-10"))
assert_in_delta k5gvl.lat, 33.1, 0.01
assert_in_delta k5gvl.lng, -96.6, 0.01
end
test "returns empty list for empty input" do
assert PreparedQueries.get_latest_positions_for_callsigns([]) == []
end
test "returns empty list for nonexistent callsigns" do
result = PreparedQueries.get_latest_positions_for_callsigns(["NONEXIST-1", "FAKE-2"])
assert result == []
end
test "is case-insensitive" do
{:ok, _} =
create_positioned_packet(%{
sender: "K5GVL-10",
base_callsign: "K5GVL",
ssid: "10",
lat: Decimal.new("33.1000"),
lon: Decimal.new("-96.6000")
})
result = PreparedQueries.get_latest_positions_for_callsigns(["k5gvl-10"])
assert length(result) == 1
assert hd(result).callsign == "K5GVL-10"
end
test "returns latest position when multiple packets exist for a callsign" do
{:ok, _} =
create_positioned_packet(%{
sender: "K5GVL-10",
base_callsign: "K5GVL",
ssid: "10",
lat: Decimal.new("33.1000"),
lon: Decimal.new("-96.6000"),
received_at: DateTime.add(DateTime.utc_now(), -3600, :second)
})
{:ok, _} =
create_positioned_packet(%{
sender: "K5GVL-10",
base_callsign: "K5GVL",
ssid: "10",
lat: Decimal.new("34.0000"),
lon: Decimal.new("-97.0000"),
received_at: DateTime.truncate(DateTime.utc_now(), :second)
})
result = PreparedQueries.get_latest_positions_for_callsigns(["K5GVL-10"])
assert length(result) == 1
position = hd(result)
assert_in_delta position.lat, 34.0, 0.01
assert_in_delta position.lng, -97.0, 0.01
end
end
end