fix: replace duplicate spatial registrations

This commit is contained in:
Graham McIntire 2026-03-22 17:12:11 -05:00
parent f1c68fbcfc
commit 7c0861f216
No known key found for this signature in database
2 changed files with 42 additions and 2 deletions

View file

@ -85,14 +85,17 @@ defmodule Aprsme.SpatialPubSub do
# Create a unique topic for this client
topic = "spatial:#{client_id}"
state = replace_existing_client(state, client_id)
# Monitor the client process
Process.monitor(pid)
ref = Process.monitor(pid)
# Update client info
client_info = %{
bounds: normalize_bounds(bounds),
topic: topic,
pid: pid
pid: pid,
monitor_ref: ref
}
# Update spatial index
@ -353,6 +356,14 @@ defmodule Aprsme.SpatialPubSub do
nil ->
state
%{bounds: bounds, monitor_ref: ref} ->
Process.demonitor(ref, [:flush])
state
|> remove_from_spatial_index(client_id, bounds)
|> update_in([:clients], &Map.delete(&1, client_id))
|> update_in([:stats, :clients_count], &max(0, &1 - 1))
%{bounds: bounds} ->
state
|> remove_from_spatial_index(client_id, bounds)
@ -361,6 +372,13 @@ defmodule Aprsme.SpatialPubSub do
end
end
defp replace_existing_client(state, client_id) do
case Map.get(state.clients, client_id) do
nil -> state
_client_info -> remove_client(state, client_id)
end
end
defp calculate_avg_clients_per_cell(spatial_index) do
non_nil_cells =
spatial_index

View file

@ -34,6 +34,28 @@ defmodule Aprsme.SpatialPubSubTest do
SpatialPubSub.unregister_client(client_id)
end
test "re-registering an existing client replaces the old viewport without inflating counts" do
client_id = "test_reregister_#{:rand.uniform(100_000)}"
bounds_1 = %{north: 41.0, south: 40.0, east: -73.0, west: -74.0}
bounds_2 = %{north: 36.0, south: 35.0, east: -79.0, west: -80.0}
before_stats = SpatialPubSub.get_stats()
assert {:ok, _topic} = SpatialPubSub.register_viewport(client_id, bounds_1)
mid_stats = SpatialPubSub.get_stats()
assert mid_stats.clients_count == before_stats.clients_count + 1
assert {:ok, _topic} = SpatialPubSub.register_viewport(client_id, bounds_2)
after_stats = SpatialPubSub.get_stats()
assert after_stats.clients_count == before_stats.clients_count + 1
state = :sys.get_state(SpatialPubSub)
assert state.clients[client_id].bounds == bounds_2
SpatialPubSub.unregister_client(client_id)
end
end
describe "duplicate packet prevention" do