Rename qsos table to contacts, qso_id to contact_id
- Migration renames table, column, all indexes, and FK constraints - Contact schema now references "contacts" table - TerrainProfile foreign key renamed from qso_id to contact_id - All code and tests updated to use contact_id
This commit is contained in:
parent
ae0e667cab
commit
da75977a55
12 changed files with 87 additions and 40 deletions
|
|
@ -9,7 +9,7 @@ defmodule Microwaveprop.Radio.Contact do
|
|||
@primary_key {:id, :binary_id, autogenerate: true}
|
||||
@foreign_key_type :binary_id
|
||||
|
||||
schema "qsos" do
|
||||
schema "contacts" do
|
||||
field :station1, :string
|
||||
field :station2, :string
|
||||
field :qso_timestamp, :utc_datetime
|
||||
|
|
|
|||
|
|
@ -10,19 +10,19 @@ defmodule Microwaveprop.Terrain do
|
|||
%TerrainProfile{}
|
||||
|> TerrainProfile.changeset(attrs)
|
||||
|> Repo.insert(
|
||||
on_conflict: {:replace_all_except, [:id, :qso_id, :inserted_at]},
|
||||
conflict_target: [:qso_id],
|
||||
on_conflict: {:replace_all_except, [:id, :contact_id, :inserted_at]},
|
||||
conflict_target: [:contact_id],
|
||||
returning: true
|
||||
)
|
||||
end
|
||||
|
||||
def get_terrain_profile(qso_id) do
|
||||
Repo.get_by(TerrainProfile, qso_id: qso_id)
|
||||
def get_terrain_profile(contact_id) do
|
||||
Repo.get_by(TerrainProfile, contact_id: contact_id)
|
||||
end
|
||||
|
||||
def has_terrain_profile?(qso_id) do
|
||||
def has_terrain_profile?(contact_id) do
|
||||
TerrainProfile
|
||||
|> where([t], t.qso_id == ^qso_id)
|
||||
|> where([t], t.contact_id == ^contact_id)
|
||||
|> Repo.exists?()
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ defmodule Microwaveprop.Terrain.TerrainProfile do
|
|||
@foreign_key_type :binary_id
|
||||
|
||||
schema "terrain_profiles" do
|
||||
belongs_to :contact, Microwaveprop.Radio.Contact, foreign_key: :qso_id
|
||||
belongs_to :contact, Microwaveprop.Radio.Contact, foreign_key: :contact_id
|
||||
field :sample_count, :integer
|
||||
field :path_points, {:array, :map}
|
||||
field :max_elevation_m, :float
|
||||
|
|
@ -21,14 +21,14 @@ defmodule Microwaveprop.Terrain.TerrainProfile do
|
|||
timestamps(type: :utc_datetime)
|
||||
end
|
||||
|
||||
@required_fields ~w(qso_id sample_count path_points verdict)a
|
||||
@required_fields ~w(contact_id sample_count path_points verdict)a
|
||||
@optional_fields ~w(max_elevation_m min_clearance_m diffraction_db fresnel_hit_count obstructed_count)a
|
||||
|
||||
def changeset(profile, attrs) do
|
||||
profile
|
||||
|> cast(attrs, @required_fields ++ @optional_fields)
|
||||
|> validate_required(@required_fields)
|
||||
|> foreign_key_constraint(:qso_id)
|
||||
|> unique_constraint([:qso_id])
|
||||
|> foreign_key_constraint(:contact_id)
|
||||
|> unique_constraint([:contact_id])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ defmodule Microwaveprop.Workers.ContactWeatherEnqueueWorker do
|
|||
contacts
|
||||
|> Enum.filter(fn contact -> contact.pos1 && contact.pos2 end)
|
||||
|> Enum.map(fn contact ->
|
||||
TerrainProfileWorker.new(%{"qso_id" => contact.id})
|
||||
TerrainProfileWorker.new(%{"contact_id" => contact.id})
|
||||
end)
|
||||
|> Enum.uniq_by(fn changeset -> changeset.changes.args end)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -14,11 +14,11 @@ defmodule Microwaveprop.Workers.TerrainProfileWorker do
|
|||
end
|
||||
|
||||
@impl Oban.Worker
|
||||
def perform(%Oban.Job{args: %{"qso_id" => qso_id}}) do
|
||||
if Terrain.has_terrain_profile?(qso_id) do
|
||||
def perform(%Oban.Job{args: %{"contact_id" => contact_id}}) do
|
||||
if Terrain.has_terrain_profile?(contact_id) do
|
||||
:ok
|
||||
else
|
||||
contact = Radio.get_contact!(qso_id)
|
||||
contact = Radio.get_contact!(contact_id)
|
||||
|
||||
with %{"lat" => lat1} <- contact.pos1,
|
||||
lon1 when is_number(lon1) <- contact.pos1["lon"] || contact.pos1["lng"],
|
||||
|
|
@ -46,7 +46,7 @@ defmodule Microwaveprop.Workers.TerrainProfileWorker do
|
|||
end)
|
||||
|
||||
Terrain.upsert_terrain_profile(%{
|
||||
qso_id: qso_id,
|
||||
contact_id: contact_id,
|
||||
sample_count: length(profile),
|
||||
path_points: path_points,
|
||||
max_elevation_m: analysis.max_elevation_m,
|
||||
|
|
@ -57,12 +57,12 @@ defmodule Microwaveprop.Workers.TerrainProfileWorker do
|
|||
verdict: analysis.verdict
|
||||
})
|
||||
|
||||
Radio.set_enrichment_status!([qso_id], :terrain_status, :complete)
|
||||
Radio.set_enrichment_status!([contact_id], :terrain_status, :complete)
|
||||
|
||||
Phoenix.PubSub.broadcast(
|
||||
Microwaveprop.PubSub,
|
||||
"contact_enrichment:#{qso_id}",
|
||||
{:terrain_ready, qso_id}
|
||||
"contact_enrichment:#{contact_id}",
|
||||
{:terrain_ready, contact_id}
|
||||
)
|
||||
|
||||
:ok
|
||||
|
|
@ -72,7 +72,7 @@ defmodule Microwaveprop.Workers.TerrainProfileWorker do
|
|||
end
|
||||
else
|
||||
_ ->
|
||||
Radio.set_enrichment_status!([qso_id], :terrain_status, :unavailable)
|
||||
Radio.set_enrichment_status!([contact_id], :terrain_status, :unavailable)
|
||||
:ok
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ defmodule MicrowavepropWeb.BackfillLive do
|
|||
obs_count = Map.get(table_counts, "surface_observations", 0)
|
||||
sounding_count = Map.get(table_counts, "soundings", 0)
|
||||
iemre_count = Map.get(table_counts, "iemre_observations", 0)
|
||||
contact_count = max(Map.get(table_counts, "qsos", 0), 1)
|
||||
contact_count = max(Map.get(table_counts, "contacts", 0), 1)
|
||||
|
||||
%{
|
||||
db_size: format_bytes(db_bytes),
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do
|
|||
end
|
||||
|
||||
@impl true
|
||||
def handle_info({:terrain_ready, _qso_id}, socket) do
|
||||
def handle_info({:terrain_ready, _contact_id}, socket) do
|
||||
contact = %{socket.assigns.contact | terrain_status: :complete}
|
||||
terrain = Terrain.get_terrain_profile(contact.id)
|
||||
soundings = socket.assigns.soundings
|
||||
|
|
@ -287,7 +287,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do
|
|||
|
||||
defp maybe_enqueue_terrain(nil, contact) do
|
||||
if contact.pos1 && contact.pos2 && contact.terrain_status in [:pending, :failed, :queued] do
|
||||
Oban.insert(TerrainProfileWorker.new(%{"qso_id" => contact.id}))
|
||||
Oban.insert(TerrainProfileWorker.new(%{"contact_id" => contact.id}))
|
||||
Radio.set_enrichment_status!([contact.id], :terrain_status, :queued)
|
||||
%{contact | terrain_status: :queued}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
defmodule Microwaveprop.Repo.Migrations.RenameQsosToContacts do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
rename table(:qsos), to: table(:contacts)
|
||||
|
||||
rename table(:terrain_profiles), :qso_id, to: :contact_id
|
||||
|
||||
# Rename indexes that reference the old table name
|
||||
execute "ALTER INDEX IF EXISTS qsos_pkey RENAME TO contacts_pkey",
|
||||
"ALTER INDEX IF EXISTS contacts_pkey RENAME TO qsos_pkey"
|
||||
|
||||
execute "ALTER INDEX IF EXISTS qsos_band_index RENAME TO contacts_band_index",
|
||||
"ALTER INDEX IF EXISTS contacts_band_index RENAME TO qsos_band_index"
|
||||
|
||||
execute "ALTER INDEX IF EXISTS qsos_distance_km_index RENAME TO contacts_distance_km_index",
|
||||
"ALTER INDEX IF EXISTS contacts_distance_km_index RENAME TO qsos_distance_km_index"
|
||||
|
||||
execute "ALTER INDEX IF EXISTS qsos_qso_timestamp_index RENAME TO contacts_qso_timestamp_index",
|
||||
"ALTER INDEX IF EXISTS contacts_qso_timestamp_index RENAME TO qsos_qso_timestamp_index"
|
||||
|
||||
execute "ALTER INDEX IF EXISTS qsos_station1_trgm_index RENAME TO contacts_station1_trgm_index",
|
||||
"ALTER INDEX IF EXISTS contacts_station1_trgm_index RENAME TO qsos_station1_trgm_index"
|
||||
|
||||
execute "ALTER INDEX IF EXISTS qsos_station2_trgm_index RENAME TO contacts_station2_trgm_index",
|
||||
"ALTER INDEX IF EXISTS contacts_station2_trgm_index RENAME TO qsos_station2_trgm_index"
|
||||
|
||||
execute "ALTER INDEX IF EXISTS qsos_hrrr_status_pending_index RENAME TO contacts_hrrr_status_pending_index",
|
||||
"ALTER INDEX IF EXISTS contacts_hrrr_status_pending_index RENAME TO qsos_hrrr_status_pending_index"
|
||||
|
||||
execute "ALTER INDEX IF EXISTS qsos_weather_status_pending_index RENAME TO contacts_weather_status_pending_index",
|
||||
"ALTER INDEX IF EXISTS contacts_weather_status_pending_index RENAME TO qsos_weather_status_pending_index"
|
||||
|
||||
execute "ALTER INDEX IF EXISTS qsos_terrain_status_pending_index RENAME TO contacts_terrain_status_pending_index",
|
||||
"ALTER INDEX IF EXISTS contacts_terrain_status_pending_index RENAME TO qsos_terrain_status_pending_index"
|
||||
|
||||
execute "ALTER INDEX IF EXISTS qsos_iemre_status_pending_index RENAME TO contacts_iemre_status_pending_index",
|
||||
"ALTER INDEX IF EXISTS contacts_iemre_status_pending_index RENAME TO qsos_iemre_status_pending_index"
|
||||
|
||||
# Rename terrain_profiles foreign key constraint
|
||||
execute "ALTER TABLE terrain_profiles RENAME CONSTRAINT terrain_profiles_qso_id_fkey TO terrain_profiles_contact_id_fkey",
|
||||
"ALTER TABLE terrain_profiles RENAME CONSTRAINT terrain_profiles_contact_id_fkey TO terrain_profiles_qso_id_fkey"
|
||||
|
||||
execute "ALTER INDEX IF EXISTS terrain_profiles_qso_id_index RENAME TO terrain_profiles_contact_id_index",
|
||||
"ALTER INDEX IF EXISTS terrain_profiles_contact_id_index RENAME TO terrain_profiles_qso_id_index"
|
||||
end
|
||||
end
|
||||
|
|
@ -28,7 +28,7 @@ defmodule Microwaveprop.Terrain.TerrainProfileTest do
|
|||
contact = create_contact()
|
||||
|
||||
attrs = %{
|
||||
qso_id: contact.id,
|
||||
contact_id: contact.id,
|
||||
sample_count: 65,
|
||||
path_points: [%{"lat" => 32.9, "lon" => -97.0, "elev" => 200.0, "dist_km" => 0.0}],
|
||||
verdict: "CLEAR"
|
||||
|
|
@ -43,7 +43,7 @@ defmodule Microwaveprop.Terrain.TerrainProfileTest do
|
|||
refute changeset.valid?
|
||||
|
||||
errors = errors_on(changeset)
|
||||
assert errors[:qso_id]
|
||||
assert errors[:contact_id]
|
||||
assert errors[:sample_count]
|
||||
assert errors[:path_points]
|
||||
assert errors[:verdict]
|
||||
|
|
@ -53,7 +53,7 @@ defmodule Microwaveprop.Terrain.TerrainProfileTest do
|
|||
contact = create_contact()
|
||||
|
||||
attrs = %{
|
||||
qso_id: contact.id,
|
||||
contact_id: contact.id,
|
||||
sample_count: 65,
|
||||
path_points: [%{"lat" => 32.9, "lon" => -97.0, "elev" => 200.0, "dist_km" => 0.0}],
|
||||
verdict: "BLOCKED",
|
||||
|
|
@ -68,11 +68,11 @@ defmodule Microwaveprop.Terrain.TerrainProfileTest do
|
|||
assert changeset.valid?
|
||||
end
|
||||
|
||||
test "enforces unique qso_id constraint on insert" do
|
||||
test "enforces unique contact_id constraint on insert" do
|
||||
contact = create_contact()
|
||||
|
||||
attrs = %{
|
||||
qso_id: contact.id,
|
||||
contact_id: contact.id,
|
||||
sample_count: 65,
|
||||
path_points: [],
|
||||
verdict: "CLEAR"
|
||||
|
|
@ -88,7 +88,7 @@ defmodule Microwaveprop.Terrain.TerrainProfileTest do
|
|||
|> TerrainProfile.changeset(attrs)
|
||||
|> Repo.insert()
|
||||
|
||||
assert errors_on(changeset)[:qso_id]
|
||||
assert errors_on(changeset)[:contact_id]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ defmodule Microwaveprop.TerrainTest do
|
|||
|
||||
defp terrain_attrs(contact) do
|
||||
%{
|
||||
qso_id: contact.id,
|
||||
contact_id: contact.id,
|
||||
sample_count: 65,
|
||||
path_points: [
|
||||
%{"lat" => 32.9, "lon" => -97.0, "elev" => 200.0, "dist_km" => 0.0},
|
||||
|
|
@ -46,12 +46,12 @@ defmodule Microwaveprop.TerrainTest do
|
|||
attrs = terrain_attrs(contact)
|
||||
|
||||
assert {:ok, profile} = Terrain.upsert_terrain_profile(attrs)
|
||||
assert profile.qso_id == contact.id
|
||||
assert profile.contact_id == contact.id
|
||||
assert profile.sample_count == 65
|
||||
assert profile.verdict == "CLEAR"
|
||||
end
|
||||
|
||||
test "upserts on conflict (same qso_id)" do
|
||||
test "upserts on conflict (same contact_id)" do
|
||||
contact = create_contact()
|
||||
attrs = terrain_attrs(contact)
|
||||
|
||||
|
|
@ -71,7 +71,7 @@ defmodule Microwaveprop.TerrainTest do
|
|||
{:ok, _} = Terrain.upsert_terrain_profile(terrain_attrs(contact))
|
||||
|
||||
profile = Terrain.get_terrain_profile(contact.id)
|
||||
assert profile.qso_id == contact.id
|
||||
assert profile.contact_id == contact.id
|
||||
end
|
||||
|
||||
test "returns nil when no profile exists" do
|
||||
|
|
|
|||
|
|
@ -370,10 +370,10 @@ defmodule Microwaveprop.Workers.ContactWeatherEnqueueWorkerTest do
|
|||
|
||||
assert length(jobs) == 1
|
||||
job = hd(jobs)
|
||||
assert job.changes.args["qso_id"] == contact.id
|
||||
assert job.changes.args["contact_id"] == contact.id
|
||||
end
|
||||
|
||||
test "deduplicates by qso_id" do
|
||||
test "deduplicates by contact_id" do
|
||||
contact = create_contact()
|
||||
|
||||
jobs = ContactWeatherEnqueueWorker.build_terrain_jobs([contact, contact])
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ defmodule Microwaveprop.Workers.TerrainProfileWorkerTest do
|
|||
|
||||
refute Terrain.has_terrain_profile?(contact.id)
|
||||
|
||||
job = TerrainProfileWorker.new(%{"qso_id" => contact.id})
|
||||
job = TerrainProfileWorker.new(%{"contact_id" => contact.id})
|
||||
assert :ok = TerrainProfileWorker.perform(%Oban.Job{args: job.changes.args})
|
||||
|
||||
assert Terrain.has_terrain_profile?(contact.id)
|
||||
|
|
@ -58,13 +58,13 @@ defmodule Microwaveprop.Workers.TerrainProfileWorkerTest do
|
|||
|
||||
{:ok, _} =
|
||||
Terrain.upsert_terrain_profile(%{
|
||||
qso_id: contact.id,
|
||||
contact_id: contact.id,
|
||||
sample_count: 65,
|
||||
path_points: [],
|
||||
verdict: "CLEAR"
|
||||
})
|
||||
|
||||
job = TerrainProfileWorker.new(%{"qso_id" => contact.id})
|
||||
job = TerrainProfileWorker.new(%{"contact_id" => contact.id})
|
||||
assert :ok = TerrainProfileWorker.perform(%Oban.Job{args: job.changes.args})
|
||||
end
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ defmodule Microwaveprop.Workers.TerrainProfileWorkerTest do
|
|||
|
||||
contact = create_contact()
|
||||
|
||||
job = TerrainProfileWorker.new(%{"qso_id" => contact.id})
|
||||
job = TerrainProfileWorker.new(%{"contact_id" => contact.id})
|
||||
assert {:error, _} = TerrainProfileWorker.perform(%Oban.Job{args: job.changes.args})
|
||||
|
||||
refute Terrain.has_terrain_profile?(contact.id)
|
||||
|
|
@ -85,7 +85,7 @@ defmodule Microwaveprop.Workers.TerrainProfileWorkerTest do
|
|||
stub_elevation_api()
|
||||
contact = create_contact(%{band: Decimal.new("10368")})
|
||||
|
||||
job = TerrainProfileWorker.new(%{"qso_id" => contact.id})
|
||||
job = TerrainProfileWorker.new(%{"contact_id" => contact.id})
|
||||
assert :ok = TerrainProfileWorker.perform(%Oban.Job{args: job.changes.args})
|
||||
|
||||
profile = Terrain.get_terrain_profile(contact.id)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue