Mission now carries bands_mhz ({:array, :integer}) — operator picks
one or more bands as multi-checkboxes. enqueue_paths_for builds the
cross product (rover x station x band) and persists each tuple as its
own Path row keyed by (mission_id, rover_location_id, station_id,
band_mhz). The path-profile worker reads band_mhz from the path
itself (legacy single-band jobs without band_mhz in args still resolve
to their unique row).
replace_mission_paths/1 is now a thin alias for reconcile_mission_paths/1
which diffs desired vs actual: stale tuples (old band that the user
unchecked, station they removed, rover-site they deleted) get dropped,
new tuples become :pending and enqueue, surviving :complete rows are
left in place — no more wholesale destruction of already-computed
paths on every edit.
The show table gains a Band column, and band_label() in the mission
summary becomes bands_label() (joins the list with commas).
67 lines
1.8 KiB
Elixir
67 lines
1.8 KiB
Elixir
defmodule Microwaveprop.Repo.Migrations.AddMultiBandRoverPlanning do
|
|
use Ecto.Migration
|
|
|
|
def up do
|
|
# Mission carries the SET of bands the operator wants to evaluate.
|
|
# `band_mhz` stays as a denormalized "primary band" for any legacy
|
|
# readers; new code reads `bands_mhz`.
|
|
alter table(:rover_missions) do
|
|
add :bands_mhz, {:array, :integer}, default: [], null: false
|
|
end
|
|
|
|
execute(
|
|
"UPDATE rover_missions SET bands_mhz = ARRAY[band_mhz] WHERE coalesce(array_length(bands_mhz, 1), 0) = 0"
|
|
)
|
|
|
|
# Each computed path is now scoped to a specific band — the worker
|
|
# uses this for its loss budget + propagation-score lookup.
|
|
alter table(:rover_mission_paths) do
|
|
add :band_mhz, :integer
|
|
end
|
|
|
|
execute("""
|
|
UPDATE rover_mission_paths p
|
|
SET band_mhz = m.band_mhz
|
|
FROM rover_missions m
|
|
WHERE p.mission_id = m.id AND p.band_mhz IS NULL
|
|
""")
|
|
|
|
alter table(:rover_mission_paths) do
|
|
modify :band_mhz, :integer, null: false
|
|
end
|
|
|
|
drop_if_exists(
|
|
unique_index(:rover_mission_paths, [:mission_id, :rover_location_id, :station_id],
|
|
name: :rover_mission_paths_unique
|
|
)
|
|
)
|
|
|
|
create unique_index(
|
|
:rover_mission_paths,
|
|
[:mission_id, :rover_location_id, :station_id, :band_mhz],
|
|
name: :rover_mission_paths_unique
|
|
)
|
|
end
|
|
|
|
def down do
|
|
drop_if_exists(
|
|
unique_index(
|
|
:rover_mission_paths,
|
|
[:mission_id, :rover_location_id, :station_id, :band_mhz],
|
|
name: :rover_mission_paths_unique
|
|
)
|
|
)
|
|
|
|
create unique_index(:rover_mission_paths, [:mission_id, :rover_location_id, :station_id],
|
|
name: :rover_mission_paths_unique
|
|
)
|
|
|
|
alter table(:rover_mission_paths) do
|
|
remove :band_mhz
|
|
end
|
|
|
|
alter table(:rover_missions) do
|
|
remove :bands_mhz
|
|
end
|
|
end
|
|
end
|