defmodule Microwaveprop.Workers.RoverMissionReconcileWorker do @moduledoc """ Async reconciler for one rover-planning mission's path matrix. Form saves (mission edits, add/remove rover site) enqueue this job instead of running the reconcile inline — for a mission with many rover sites × stations × bands the inline path produced a multi- hundred-row Multi transaction + as many `Oban.insert/1` calls, which made the form submit feel sluggish. The reconcile itself is idempotent: deleting stale (mission_id, rover_location_id, station_id, band_mhz) rows, leaving :complete rows in place, and enqueueing per-pair compute jobs only for the tuples that aren't already represented. """ use Oban.Pro.Worker, queue: :terrain, priority: 3, max_attempts: 3, unique: [ period: 60, keys: [:mission_id], states: :incomplete ] import Ecto.Query alias Microwaveprop.Repo alias Microwaveprop.RoverPlanning alias Microwaveprop.RoverPlanning.Mission alias Microwaveprop.RoverPlanning.Station @impl Oban.Pro.Worker def process(%Oban.Job{args: %{"mission_id" => mission_id}}) do case Repo.get(Mission, mission_id) do nil -> :ok mission -> mission |> Repo.preload([:user, stations: from(s in Station, order_by: s.position)]) |> RoverPlanning.reconcile_mission_paths() end end end