test: override stale distance_km when filling a missing pos

Makes the 'always recompute' intent explicit by removing the dead-code
short-circuit in add_distance_change — the candidate query already
requires at least one nil pos, so any previously stored distance is
tied to a stale grid/pos pair and must be overwritten.
This commit is contained in:
Graham McIntire 2026-04-16 14:08:10 -05:00
parent a669e60735
commit f693cb5b56
No known key found for this signature in database
GPG key ID: F4ABF488E6029E59
2 changed files with 41 additions and 15 deletions

View file

@ -78,23 +78,20 @@ defmodule Microwaveprop.Workers.ContactPositionBackfillWorker do
defp add_pos_change(updates, _field, _existing, nil), do: updates
defp add_pos_change(updates, field, _nil, new), do: [{field, new} | updates]
defp add_distance_change(updates, contact, pos1, pos2) do
cond do
pos1 == nil or pos2 == nil ->
updates
# Always overwrite distance_km when both positions resolve — the candidate
# query only selects contacts with at least one nil pos, so any previously
# stored distance is tied to a stale grid/pos pair.
defp add_distance_change(updates, _contact, nil, _pos2), do: updates
defp add_distance_change(updates, _contact, _pos1, nil), do: updates
not is_nil(contact.distance_km) and contact.pos1 != nil and contact.pos2 != nil ->
updates
defp add_distance_change(updates, _contact, pos1, pos2) do
distance =
pos1["lat"]
|> Radio.haversine_km(pos1["lon"], pos2["lat"], pos2["lon"])
|> round()
|> Decimal.new()
true ->
distance =
pos1["lat"]
|> Radio.haversine_km(pos1["lon"], pos2["lat"], pos2["lon"])
|> round()
|> Decimal.new()
[{:distance_km, distance} | updates]
end
[{:distance_km, distance} | updates]
end
defp maybe_touch_updated_at([]), do: []

View file

@ -136,5 +136,34 @@ defmodule Microwaveprop.Workers.ContactPositionBackfillWorkerTest do
distance = Decimal.to_integer(reloaded.distance_km)
assert distance > 0 and distance < 1000
end
# Scenario: user updates grid1 to higher precision via direct DB write and
# nulls pos1 but leaves distance_km at the old (less-precise) value. Worker
# must re-resolve pos1 AND overwrite the stale distance_km.
test "overrides stale distance_km when filling a missing pos" do
pos2 = %{"lat" => 30.3, "lon" => -97.7}
stale_distance = Decimal.new(9999)
contact =
insert_raw_contact!(%{
grid1: "EM12",
grid2: "EM00",
pos1: nil,
pos2: pos2,
distance_km: stale_distance
})
assert {:ok, %{updated: 1}} = ContactPositionBackfillWorker.perform(%Oban.Job{args: %{}})
reloaded = Repo.reload!(contact)
assert %{"lat" => _, "lon" => _} = reloaded.pos1
refute Decimal.equal?(reloaded.distance_km, stale_distance),
"expected distance_km to be recomputed from refined grid, got #{reloaded.distance_km}"
# EM12 <-> EM00 is ~333 km; sanity check the new value is in that ballpark.
new_distance = Decimal.to_integer(reloaded.distance_km)
assert new_distance > 0 and new_distance < 1000
end
end
end