diff --git a/.dialyzer_ignore.exs b/.dialyzer_ignore.exs new file mode 100644 index 00000000..ce5b7351 --- /dev/null +++ b/.dialyzer_ignore.exs @@ -0,0 +1,10 @@ +# LiveTable.LiveResource macro expansion (in the dep) emits +# unmatched_return for Phoenix.PubSub.subscribe/Oban.insert calls +# it generates inside handle_event/3 and maybe_subscribe/1. Can't +# fix without forking the dep; suppress at the `use` line only. +[ + {"lib/microwaveprop_web/live/admin/contact_edit_live.ex", :unmatched_return, 4}, + {"lib/microwaveprop_web/live/beacon_live/index.ex", :unmatched_return, 4}, + {"lib/microwaveprop_web/live/contact_live/index.ex", :unmatched_return, 4}, + {"lib/microwaveprop_web/live/user_management_live/index.ex", :unmatched_return, 4} +] diff --git a/lib/microwaveprop/accounts/scope.ex b/lib/microwaveprop/accounts/scope.ex index f73da130..c497273a 100644 --- a/lib/microwaveprop/accounts/scope.ex +++ b/lib/microwaveprop/accounts/scope.ex @@ -18,6 +18,8 @@ defmodule Microwaveprop.Accounts.Scope do alias Microwaveprop.Accounts.User + @type t :: %__MODULE__{user: User.t() | nil} + defstruct user: nil @doc """ diff --git a/lib/microwaveprop/application.ex b/lib/microwaveprop/application.ex index 0d7aa680..4e37933c 100644 --- a/lib/microwaveprop/application.ex +++ b/lib/microwaveprop/application.ex @@ -46,7 +46,7 @@ defmodule Microwaveprop.Application do result = Supervisor.start_link(children, opts) # Run migrations after Repo is started - Microwaveprop.Release.migrate() + _ = Microwaveprop.Release.migrate() # Warm GridCache from the latest persisted ProfilesFile so /weather # has data immediately after a pod restart. Runs after the GridCache @@ -56,7 +56,7 @@ defmodule Microwaveprop.Application do # master: when executed here the loaded rows live on the app master's # heap and never GC (it's idle after boot), pinning ~800 MiB for the # lifetime of the pod. - Task.start(fn -> Microwaveprop.Weather.warm_grid_cache_from_latest_profile() end) + {:ok, _pid} = Task.start(fn -> Microwaveprop.Weather.warm_grid_cache_from_latest_profile() end) # Load ML model in dev/test only (Nx/Axon not compiled for prod) if Application.get_env(:microwaveprop, :load_ml_model, false) do diff --git a/lib/microwaveprop/backtest/features.ex b/lib/microwaveprop/backtest/features.ex index 26a726d2..c4a0e91a 100644 --- a/lib/microwaveprop/backtest/features.ex +++ b/lib/microwaveprop/backtest/features.ex @@ -269,7 +269,7 @@ defmodule Microwaveprop.Backtest.Features do it documents the intended API; the backtest will only work once the pipeline is live. """ - @spec distance_to_front(float, float, DateTime.t()) :: float | nil + @spec distance_to_front(float, float, DateTime.t()) :: nil def distance_to_front(_lat, _lon, _valid_time), do: nil @doc """ @@ -278,7 +278,7 @@ defmodule Microwaveprop.Backtest.Features do bearing, so this is only usable in QSO-level scoring, not grid scoring. Placeholder until Phase 5.4. """ - @spec parallel_to_front(float, float, DateTime.t()) :: float | nil + @spec parallel_to_front(float, float, DateTime.t()) :: nil def parallel_to_front(_lat, _lon, _valid_time), do: nil @doc "Duct usable for 10 GHz." diff --git a/lib/microwaveprop/beacons.ex b/lib/microwaveprop/beacons.ex index 99d1f615..d9770216 100644 --- a/lib/microwaveprop/beacons.ex +++ b/lib/microwaveprop/beacons.ex @@ -72,7 +72,7 @@ defmodule Microwaveprop.Beacons do end @doc "Gets a single beacon. Raises if not found." - @spec get_beacon!(Ecto.UUID.t()) :: Beacon.t() + @spec get_beacon!(Ecto.UUID.t()) :: Beacon.t() | nil | [map()] def get_beacon!(id), do: Beacon |> Repo.get!(id) |> Repo.preload(:user) @doc """ @@ -119,7 +119,7 @@ defmodule Microwaveprop.Beacons do def delete_beacon(%Beacon{} = beacon) do case Repo.delete(beacon) do {:ok, beacon} -> - broadcast({:deleted, beacon}) + _ = broadcast({:deleted, beacon}) {:ok, beacon} other -> @@ -134,7 +134,7 @@ defmodule Microwaveprop.Beacons do end defp broadcast_if_ok({:ok, beacon} = result, type) do - broadcast({type, beacon}) + _ = broadcast({type, beacon}) result end diff --git a/lib/microwaveprop/cache.ex b/lib/microwaveprop/cache.ex index f3a7cea9..34435108 100644 --- a/lib/microwaveprop/cache.ex +++ b/lib/microwaveprop/cache.ex @@ -58,13 +58,14 @@ defmodule Microwaveprop.Cache do @impl true def init(_opts) do - :ets.new(@table, [ - :set, - :named_table, - :public, - read_concurrency: true, - write_concurrency: true - ]) + _ = + :ets.new(@table, [ + :set, + :named_table, + :public, + read_concurrency: true, + write_concurrency: true + ]) {:ok, %{}} end diff --git a/lib/microwaveprop/ionosphere/giro_client.ex b/lib/microwaveprop/ionosphere/giro_client.ex index c08d8f8e..c7ecbbeb 100644 --- a/lib/microwaveprop/ionosphere/giro_client.ex +++ b/lib/microwaveprop/ionosphere/giro_client.ex @@ -172,8 +172,6 @@ defmodule Microwaveprop.Ionosphere.GiroClient do } end - defp parse_int(nil), do: nil - defp parse_int(s) do case Integer.parse(s) do {n, ""} -> n diff --git a/lib/microwaveprop/propagation/freshness_monitor.ex b/lib/microwaveprop/propagation/freshness_monitor.ex index 1faf7db8..d8e53462 100644 --- a/lib/microwaveprop/propagation/freshness_monitor.ex +++ b/lib/microwaveprop/propagation/freshness_monitor.ex @@ -32,7 +32,7 @@ defmodule Microwaveprop.Propagation.FreshnessMonitor do @impl true def handle_info(:check, state) do - check_freshness() + _ = check_freshness() Process.send_after(self(), :check, @check_interval) {:noreply, state} end diff --git a/lib/microwaveprop/propagation/notify_listener.ex b/lib/microwaveprop/propagation/notify_listener.ex index 30c8f339..41b108f9 100644 --- a/lib/microwaveprop/propagation/notify_listener.ex +++ b/lib/microwaveprop/propagation/notify_listener.ex @@ -97,7 +97,7 @@ defmodule Microwaveprop.Propagation.NotifyListener do # unbounded when Rust covers many forecast hours back-to-back. ScoreCache.prune_older_than(DateTime.add(DateTime.utc_now(), -2, :hour)) - Phoenix.PubSub.broadcast(@pubsub, @topic, {:propagation_updated, [valid_time]}) + _ = Phoenix.PubSub.broadcast(@pubsub, @topic, {:propagation_updated, [valid_time]}) if err > 0 do Logger.warning("NotifyListener: warmed #{ok} bands, #{err} failed for valid_time=#{valid_time}") diff --git a/lib/microwaveprop/propagation/run_timing.ex b/lib/microwaveprop/propagation/run_timing.ex index 782e2028..1535f668 100644 --- a/lib/microwaveprop/propagation/run_timing.ex +++ b/lib/microwaveprop/propagation/run_timing.ex @@ -10,6 +10,8 @@ defmodule Microwaveprop.Propagation.RunTiming do import Ecto.Changeset + @type t :: %__MODULE__{} + @primary_key {:id, :binary_id, autogenerate: true} @foreign_key_type :binary_id schema "propagation_run_timings" do diff --git a/lib/microwaveprop/propagation/score_cache.ex b/lib/microwaveprop/propagation/score_cache.ex index 8e2cb3be..58ac8f9f 100644 --- a/lib/microwaveprop/propagation/score_cache.ex +++ b/lib/microwaveprop/propagation/score_cache.ex @@ -83,7 +83,7 @@ defmodule Microwaveprop.Propagation.ScoreCache do """ @spec broadcast_put(non_neg_integer(), DateTime.t(), [score()]) :: :ok def broadcast_put(band_mhz, valid_time, scores) do - PubSub.broadcast(@pubsub, @topic, {:cache_refresh, band_mhz, valid_time, scores}) + _ = PubSub.broadcast(@pubsub, @topic, {:cache_refresh, band_mhz, valid_time, scores}) :ok end @@ -122,8 +122,8 @@ defmodule Microwaveprop.Propagation.ScoreCache do @impl true def init(_opts) do - :ets.new(@table, [:set, :named_table, :public, :compressed, read_concurrency: true]) - PubSub.subscribe(@pubsub, @topic) + _ = :ets.new(@table, [:set, :named_table, :public, :compressed, read_concurrency: true]) + :ok = PubSub.subscribe(@pubsub, @topic) {:ok, %{}} end diff --git a/lib/microwaveprop/propagation/score_cache_reconciler.ex b/lib/microwaveprop/propagation/score_cache_reconciler.ex index 2bab079a..31bdf787 100644 --- a/lib/microwaveprop/propagation/score_cache_reconciler.ex +++ b/lib/microwaveprop/propagation/score_cache_reconciler.ex @@ -56,9 +56,10 @@ defmodule Microwaveprop.Propagation.ScoreCacheReconciler do def init(opts) do interval = Keyword.get(opts, :interval_ms, @default_interval_ms) - if Keyword.get(opts, :run_on_start, true) do - Process.send_after(self(), :sweep, 500) - end + _ = + if Keyword.get(opts, :run_on_start, true) do + _ = Process.send_after(self(), :sweep, 500) + end {:ok, %{interval_ms: interval}} end diff --git a/lib/microwaveprop/radio.ex b/lib/microwaveprop/radio.ex index af24f89e..5db7702e 100644 --- a/lib/microwaveprop/radio.ex +++ b/lib/microwaveprop/radio.ex @@ -980,7 +980,7 @@ defmodule Microwaveprop.Radio do # Apply changes to contact contact = Repo.get!(Contact, edit.contact_id) - apply_edit_to_contact(contact, edit.proposed_changes) + _ = apply_edit_to_contact(contact, edit.proposed_changes) Repo.preload(approved, [:user, :contact, :reviewed_by]) end) diff --git a/lib/microwaveprop/release.ex b/lib/microwaveprop/release.ex index 420e4c2f..21a0a02e 100644 --- a/lib/microwaveprop/release.ex +++ b/lib/microwaveprop/release.ex @@ -21,7 +21,7 @@ defmodule Microwaveprop.Release do @app :microwaveprop def migrate do - load_app() + _ = load_app() for repo <- repos() do {:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :up, all: true)) @@ -29,30 +29,30 @@ defmodule Microwaveprop.Release do end def rollback(repo, version) do - load_app() + _ = load_app() {:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :down, to: version)) end def backtest(feature_name) when is_binary(feature_name) do - start_app() + _ = start_app() {:ok, job} = Oban.insert(AdminTaskWorker.new(%{task: "backtest", feature: feature_name})) IO.puts("Enqueued backtest for #{feature_name} (job #{job.id})") end def backtest_all do - start_app() + _ = start_app() {:ok, job} = Oban.insert(AdminTaskWorker.new(%{task: "backtest_all"})) IO.puts("Enqueued consolidated backtest (job #{job.id})") end def climatology(min_samples \\ 3) do - start_app() + _ = start_app() {:ok, job} = Oban.insert(AdminTaskWorker.new(%{task: "climatology", min_samples: min_samples})) IO.puts("Enqueued climatology build (job #{job.id})") end def native_backfill(limit \\ 500) do - start_app() + _ = start_app() %{rows: rows} = Microwaveprop.Repo.query!( @@ -88,7 +88,7 @@ defmodule Microwaveprop.Release do end def recalibrate do - start_app() + _ = start_app() {:ok, job} = Oban.insert(AdminTaskWorker.new(%{task: "recalibrate"})) IO.puts("Enqueued recalibration (job #{job.id})") end @@ -98,12 +98,12 @@ defmodule Microwaveprop.Release do # files on disk. Left as a stub that tells the operator what # happened if they shell into a running release from muscle memory. def scorer_diff(_new_weights_json) do - start_app() + _ = start_app() IO.puts("scorer_diff is disabled: propagation_scores table + factors storage have been dropped.") end def native_derive(limit \\ 10_000) do - start_app() + _ = start_app() {:ok, job} = Oban.insert(AdminTaskWorker.new(%{task: "native_derive", limit: limit})) IO.puts("Enqueued native derive (job #{job.id})") end @@ -113,7 +113,7 @@ defmodule Microwaveprop.Release do end defp load_app do - Application.ensure_all_started(:ssl) + {:ok, _} = Application.ensure_all_started(:ssl) Application.ensure_loaded(@app) end diff --git a/lib/microwaveprop/repo_listener.ex b/lib/microwaveprop/repo_listener.ex index 807481b5..5bcee981 100644 --- a/lib/microwaveprop/repo_listener.ex +++ b/lib/microwaveprop/repo_listener.ex @@ -38,33 +38,35 @@ defmodule Microwaveprop.RepoListener do @impl true def handle_info({:notification, _pid, _ref, "contact_status_changed", payload}, state) do - case Jason.decode(payload) do - {:ok, data} -> - Phoenix.PubSub.broadcast( - Microwaveprop.PubSub, - "db:contact_status", - {:contact_status_changed, data} - ) + _ = + case Jason.decode(payload) do + {:ok, data} -> + Phoenix.PubSub.broadcast( + Microwaveprop.PubSub, + "db:contact_status", + {:contact_status_changed, data} + ) - _ -> - :ok - end + _ -> + :ok + end {:noreply, state} end def handle_info({:notification, _pid, _ref, "oban_job_changed", payload}, state) do - case Jason.decode(payload) do - {:ok, data} -> - Phoenix.PubSub.broadcast( - Microwaveprop.PubSub, - "db:oban_jobs", - {:oban_job_changed, data} - ) + _ = + case Jason.decode(payload) do + {:ok, data} -> + Phoenix.PubSub.broadcast( + Microwaveprop.PubSub, + "db:oban_jobs", + {:oban_job_changed, data} + ) - _ -> - :ok - end + _ -> + :ok + end {:noreply, state} end diff --git a/lib/microwaveprop/terrain/srtm.ex b/lib/microwaveprop/terrain/srtm.ex index 432c7039..fc4fd518 100644 --- a/lib/microwaveprop/terrain/srtm.ex +++ b/lib/microwaveprop/terrain/srtm.ex @@ -93,7 +93,7 @@ defmodule Microwaveprop.Terrain.Srtm do end @spec fetch_elevation_profile(float(), float(), float(), float(), String.t(), pos_integer(), keyword()) :: - {:ok, list(map())} | {:error, term()} + {:ok, list(map())} def fetch_elevation_profile(lat1, lon1, lat2, lon2, tiles_dir, n \\ 64, opts \\ []) do pts = sample_path(lat1, lon1, lat2, lon2, n) dist_km = haversine_km(lat1, lon1, lat2, lon2) @@ -130,7 +130,7 @@ defmodule Microwaveprop.Terrain.Srtm do {:error, :void} end - :file.close(fd) + _ = :file.close(fd) result end diff --git a/lib/microwaveprop/weather.ex b/lib/microwaveprop/weather.ex index 75a314c4..b0bebf17 100644 --- a/lib/microwaveprop/weather.ex +++ b/lib/microwaveprop/weather.ex @@ -527,27 +527,30 @@ defmodule Microwaveprop.Weather do end defp kickoff_async_grid_fill(valid_time) do - if GridCache.claim_fill(valid_time) do - Task.start(fn -> - try do - Logger.info("Weather.grid_cache async fill starting for #{valid_time}") - warm_grid_cache_and_broadcast(valid_time) + _ = + if GridCache.claim_fill(valid_time) do + {:ok, _pid} = + Task.start(fn -> + try do + Logger.info("Weather.grid_cache async fill starting for #{valid_time}") + warm_grid_cache_and_broadcast(valid_time) - Phoenix.PubSub.broadcast( - Microwaveprop.PubSub, - "weather:updated", - {:weather_updated, valid_time} - ) + _ = + Phoenix.PubSub.broadcast( + Microwaveprop.PubSub, + "weather:updated", + {:weather_updated, valid_time} + ) - Logger.info("Weather.grid_cache async fill complete for #{valid_time}") - rescue - e -> - Logger.error("Weather.grid_cache async fill failed: #{inspect(e)}") - after - GridCache.release_fill(valid_time) - end - end) - end + Logger.info("Weather.grid_cache async fill complete for #{valid_time}") + rescue + e -> + Logger.error("Weather.grid_cache async fill failed: #{inspect(e)}") + after + GridCache.release_fill(valid_time) + end + end) + end :ok end diff --git a/lib/microwaveprop/weather/frontal_analysis.ex b/lib/microwaveprop/weather/frontal_analysis.ex index dd255161..94f08526 100644 --- a/lib/microwaveprop/weather/frontal_analysis.ex +++ b/lib/microwaveprop/weather/frontal_analysis.ex @@ -124,7 +124,7 @@ defmodule Microwaveprop.Weather.FrontalAnalysis do @doc """ Angle between a QSO path and the nearest front (0° = parallel, 90° = crosses). """ - @spec path_front_angle(float(), float()) :: float() + @spec path_front_angle(float(), float()) :: number() def path_front_angle(path_bearing_deg, front_bearing_deg) do diff = abs(path_bearing_deg - front_bearing_deg) diff = if diff > 180, do: 360 - diff, else: diff diff --git a/lib/microwaveprop/weather/grib2/extractor.ex b/lib/microwaveprop/weather/grib2/extractor.ex index 17b30e4d..f6be53e3 100644 --- a/lib/microwaveprop/weather/grib2/extractor.ex +++ b/lib/microwaveprop/weather/grib2/extractor.ex @@ -93,7 +93,7 @@ defmodule Microwaveprop.Weather.Grib2.Extractor do For HRRR scan_mode=64 (j positive, i positive, i consecutive): index = j * nx + i """ @spec linear_index({non_neg_integer(), non_neg_integer()}, pos_integer(), non_neg_integer()) :: - non_neg_integer() + number() def linear_index({i, j}, nx, _scan_mode) do j * nx + i end diff --git a/lib/microwaveprop/weather/grib2/wgrib2.ex b/lib/microwaveprop/weather/grib2/wgrib2.ex index 8897e29c..fc068035 100644 --- a/lib/microwaveprop/weather/grib2/wgrib2.ex +++ b/lib/microwaveprop/weather/grib2/wgrib2.ex @@ -295,7 +295,7 @@ defmodule Microwaveprop.Weather.Grib2.Wgrib2 do {:error, "wgrib2 failed (exit #{exit_code}): #{String.slice(output, 0, 200)}"} end after - File.rm(tmp_grib) + _ = File.rm(tmp_grib) File.rm(tmp_bin) end end diff --git a/lib/microwaveprop/weather/grid_cache.ex b/lib/microwaveprop/weather/grid_cache.ex index e87ed74d..46597789 100644 --- a/lib/microwaveprop/weather/grid_cache.ex +++ b/lib/microwaveprop/weather/grid_cache.ex @@ -69,7 +69,7 @@ defmodule Microwaveprop.Weather.GridCache do @doc "Insert locally AND broadcast to peer nodes via PubSub." @spec broadcast_put(DateTime.t(), [row()]) :: :ok def broadcast_put(valid_time, rows) do - PubSub.broadcast(@pubsub, @topic, {:weather_cache_refresh, valid_time, rows}) + _ = PubSub.broadcast(@pubsub, @topic, {:weather_cache_refresh, valid_time, rows}) :ok end @@ -122,9 +122,9 @@ defmodule Microwaveprop.Weather.GridCache do @impl true def init(_opts) do - :ets.new(@table, [:set, :named_table, :public, :compressed, read_concurrency: true]) - :ets.new(@lock_table, [:set, :named_table, :protected]) - PubSub.subscribe(@pubsub, @topic) + _ = :ets.new(@table, [:set, :named_table, :public, :compressed, read_concurrency: true]) + _ = :ets.new(@lock_table, [:set, :named_table, :protected]) + :ok = PubSub.subscribe(@pubsub, @topic) {:ok, %{monitors: %{}}} end diff --git a/lib/microwaveprop/weather/hrrr_point_enqueuer.ex b/lib/microwaveprop/weather/hrrr_point_enqueuer.ex index b3362e07..175e8952 100644 --- a/lib/microwaveprop/weather/hrrr_point_enqueuer.ex +++ b/lib/microwaveprop/weather/hrrr_point_enqueuer.ex @@ -50,46 +50,47 @@ defmodule Microwaveprop.Weather.HrrrPointEnqueuer do # || union on round-trip. id = Ecto.UUID.bingenerate() - Repo.insert_all( - "hrrr_fetch_tasks", - [ - %{ - id: id, - valid_time: valid_time, - points: json_points, - status: "queued", - attempt: 0, - inserted_at: now, - updated_at: now - } - ], - on_conflict: - from(t in "hrrr_fetch_tasks", - update: [ - set: [ - points: - fragment( - "(SELECT COALESCE(jsonb_agg(DISTINCT p), '[]'::jsonb) FROM jsonb_array_elements(? || EXCLUDED.points) AS p)", - t.points - ), - status: - fragment( - "CASE WHEN ? IN ('done', 'failed') THEN 'queued' ELSE ? END", - t.status, - t.status - ), - attempt: - fragment( - "CASE WHEN ? IN ('done', 'failed') THEN 0 ELSE ? END", - t.status, - t.attempt - ), - updated_at: ^now + _ = + Repo.insert_all( + "hrrr_fetch_tasks", + [ + %{ + id: id, + valid_time: valid_time, + points: json_points, + status: "queued", + attempt: 0, + inserted_at: now, + updated_at: now + } + ], + on_conflict: + from(t in "hrrr_fetch_tasks", + update: [ + set: [ + points: + fragment( + "(SELECT COALESCE(jsonb_agg(DISTINCT p), '[]'::jsonb) FROM jsonb_array_elements(? || EXCLUDED.points) AS p)", + t.points + ), + status: + fragment( + "CASE WHEN ? IN ('done', 'failed') THEN 'queued' ELSE ? END", + t.status, + t.status + ), + attempt: + fragment( + "CASE WHEN ? IN ('done', 'failed') THEN 0 ELSE ? END", + t.status, + t.attempt + ), + updated_at: ^now + ] ] - ] - ), - conflict_target: [:valid_time] - ) + ), + conflict_target: [:valid_time] + ) acc + 1 end) diff --git a/lib/microwaveprop/weather/nexrad_cache.ex b/lib/microwaveprop/weather/nexrad_cache.ex index 5ebd440b..79917457 100644 --- a/lib/microwaveprop/weather/nexrad_cache.ex +++ b/lib/microwaveprop/weather/nexrad_cache.ex @@ -73,7 +73,7 @@ defmodule Microwaveprop.Weather.NexradCache do @impl true def init(_opts) do - :ets.new(@table, [:set, :named_table, :public, :compressed, read_concurrency: true]) + _ = :ets.new(@table, [:set, :named_table, :public, :compressed, read_concurrency: true]) {:ok, %{}} end end diff --git a/lib/microwaveprop/workers/backfill_enqueue_worker.ex b/lib/microwaveprop/workers/backfill_enqueue_worker.ex index 074ab609..9255fb18 100644 --- a/lib/microwaveprop/workers/backfill_enqueue_worker.ex +++ b/lib/microwaveprop/workers/backfill_enqueue_worker.ex @@ -72,11 +72,12 @@ defmodule Microwaveprop.Workers.BackfillEnqueueWorker do Enum.each(contacts, &ContactWeatherEnqueueWorker.enqueue_for_contact(&1, types)) - Phoenix.PubSub.broadcast( - Microwaveprop.PubSub, - "backfill:enqueue_complete", - {:enqueue_complete, count} - ) + _ = + Phoenix.PubSub.broadcast( + Microwaveprop.PubSub, + "backfill:enqueue_complete", + {:enqueue_complete, count} + ) :ok end diff --git a/lib/microwaveprop/workers/canadian_sounding_fetch_worker.ex b/lib/microwaveprop/workers/canadian_sounding_fetch_worker.ex index a4740c3d..d1ac772e 100644 --- a/lib/microwaveprop/workers/canadian_sounding_fetch_worker.ex +++ b/lib/microwaveprop/workers/canadian_sounding_fetch_worker.ex @@ -61,12 +61,10 @@ defmodule Microwaveprop.Workers.CanadianSoundingFetchWorker do def most_recent_sounding_time(%DateTime{} = now) do cutoff = DateTime.add(now, -@publish_delay_seconds, :second) - cond do - cutoff.hour >= 12 -> - %{cutoff | hour: 12, minute: 0, second: 0, microsecond: {0, 0}} - - cutoff.hour >= 0 and DateTime.compare(cutoff, %{cutoff | hour: 0, minute: 0, second: 0, microsecond: {0, 0}}) != :lt -> - %{cutoff | hour: 0, minute: 0, second: 0, microsecond: {0, 0}} + if cutoff.hour >= 12 do + %{cutoff | hour: 12, minute: 0, second: 0, microsecond: {0, 0}} + else + %{cutoff | hour: 0, minute: 0, second: 0, microsecond: {0, 0}} end end @@ -91,7 +89,7 @@ defmodule Microwaveprop.Workers.CanadianSoundingFetchWorker do case UwyoSoundingClient.fetch_sounding(uwyo_code, sounding_time) do {:ok, [%{profile: profile} | _]} when profile != [] -> attrs = build_attrs(sounding_time, profile) - Weather.upsert_sounding(station, attrs) + _ = Weather.upsert_sounding(station, attrs) Logger.info("CanadianSoundings: #{code} ingested sounding with #{length(profile)} levels") diff --git a/lib/microwaveprop/workers/contact_import_worker.ex b/lib/microwaveprop/workers/contact_import_worker.ex index 81dd8fa9..642ce21a 100644 --- a/lib/microwaveprop/workers/contact_import_worker.ex +++ b/lib/microwaveprop/workers/contact_import_worker.ex @@ -50,7 +50,7 @@ defmodule Microwaveprop.Workers.ContactImportWorker do updates = build_counter_updates(commit_result, length(chunk)) updated_run = apply_chunk_updates(run.id, updates) - broadcast(run.id, updated_run) + _ = broadcast(run.id, updated_run) :ok end diff --git a/lib/microwaveprop/workers/contact_weather_enqueue_worker.ex b/lib/microwaveprop/workers/contact_weather_enqueue_worker.ex index c60d0f8a..5ecda2cd 100644 --- a/lib/microwaveprop/workers/contact_weather_enqueue_worker.ex +++ b/lib/microwaveprop/workers/contact_weather_enqueue_worker.ex @@ -44,15 +44,16 @@ defmodule Microwaveprop.Workers.ContactWeatherEnqueueWorker do # and UPSERT-union means a backfill tick that adds a new contact in # an already-scheduled hour collapses into the existing row instead # of creating a duplicate fetch. - if :hrrr in types do - {:ok, _} = HrrrPointEnqueuer.enqueue_for_contacts([contact]) - end + _ = + if :hrrr in types do + {:ok, _} = HrrrPointEnqueuer.enqueue_for_contacts([contact]) + end # NARR jobs must go through Oban.insert/1 so the worker's unique # constraint is honored; Oban OSS insert_all does not check uniqueness. insert_unique(jobs_by_type[:narr]) - mark_enrichment_statuses(contact, types, jobs_by_type) + _ = mark_enrichment_statuses(contact, types, jobs_by_type) :ok end @@ -97,9 +98,10 @@ defmodule Microwaveprop.Workers.ContactWeatherEnqueueWorker do defp mark_enrichment_statuses(contact, types, jobs_by_type) do ids = [contact.id] - if contact.pos1 do - mark_pos1_statuses(contact, ids, types, jobs_by_type) - end + _ = + if contact.pos1 do + mark_pos1_statuses(contact, ids, types, jobs_by_type) + end if contact.pos1 && contact.pos2 do mark_path_statuses(contact, ids, types, jobs_by_type) @@ -113,22 +115,22 @@ defmodule Microwaveprop.Workers.ContactWeatherEnqueueWorker do end defp mark_missing_path_statuses(ids, types) do - if :terrain in types, do: Radio.set_enrichment_status!(ids, :terrain_status, :unavailable) - if :radar in types, do: Radio.set_enrichment_status!(ids, :radar_status, :unavailable) + _ = if :terrain in types, do: Radio.set_enrichment_status!(ids, :terrain_status, :unavailable) + _ = if :radar in types, do: Radio.set_enrichment_status!(ids, :radar_status, :unavailable) if :mechanism in types, do: Radio.set_enrichment_status!(ids, :mechanism_status, :unavailable) end defp mark_pos1_statuses(contact, ids, types, jobs_by_type) do - if :weather in types, do: mark_status!(ids, :weather_status, jobs_by_type[:weather]) - if :hrrr in types, do: mark_hrrr_status!(contact, ids, jobs_by_type[:hrrr]) + _ = if :weather in types, do: mark_status!(ids, :weather_status, jobs_by_type[:weather]) + _ = if :hrrr in types, do: mark_hrrr_status!(contact, ids, jobs_by_type[:hrrr]) if :iemre in types, do: mark_status!(ids, :iemre_status, jobs_by_type[:iemre]) end defp mark_path_statuses(contact, ids, types, jobs_by_type) do - if :terrain in types, do: mark_status!(ids, :terrain_status, jobs_by_type[:terrain]) - if :radar in types, do: mark_radar_status!(contact, ids, jobs_by_type[:radar]) + _ = if :terrain in types, do: mark_status!(ids, :terrain_status, jobs_by_type[:terrain]) + _ = if :radar in types, do: mark_radar_status!(contact, ids, jobs_by_type[:radar]) if :mechanism in types, do: mark_status!(ids, :mechanism_status, jobs_by_type[:mechanism]) @@ -178,7 +180,7 @@ defmodule Microwaveprop.Workers.ContactWeatherEnqueueWorker do :ok contacts -> - Radio.backfill_distances(contacts) + _ = Radio.backfill_distances(contacts) jobs = build_weather_jobs(contacts) @@ -187,7 +189,7 @@ defmodule Microwaveprop.Workers.ContactWeatherEnqueueWorker do end ids = Enum.map(contacts, & &1.id) - Radio.mark_weather_queued!(ids) + _ = Radio.mark_weather_queued!(ids) enqueue_weather_jobs() end @@ -206,7 +208,7 @@ defmodule Microwaveprop.Workers.ContactWeatherEnqueueWorker do {:ok, _} = HrrrPointEnqueuer.enqueue_for_contacts(contacts) ids = Enum.map(contacts, & &1.id) - Radio.mark_hrrr_queued!(ids) + _ = Radio.mark_hrrr_queued!(ids) enqueue_hrrr_jobs() end @@ -225,7 +227,7 @@ defmodule Microwaveprop.Workers.ContactWeatherEnqueueWorker do end ids = Enum.map(contacts, & &1.id) - Radio.mark_terrain_queued!(ids) + _ = Radio.mark_terrain_queued!(ids) enqueue_terrain_jobs() end @@ -350,7 +352,7 @@ defmodule Microwaveprop.Workers.ContactWeatherEnqueueWorker do end ids = Enum.map(contacts, & &1.id) - Radio.mark_iemre_queued!(ids) + _ = Radio.mark_iemre_queued!(ids) enqueue_iemre_jobs() end diff --git a/lib/microwaveprop/workers/gefs_fetch_worker.ex b/lib/microwaveprop/workers/gefs_fetch_worker.ex index 782ed223..75484059 100644 --- a/lib/microwaveprop/workers/gefs_fetch_worker.ex +++ b/lib/microwaveprop/workers/gefs_fetch_worker.ex @@ -175,14 +175,15 @@ defmodule Microwaveprop.Workers.GefsFetchWorker do end) |> Enum.to_list() - case Propagation.replace_scores(scores, valid_time) do - {:ok, count} -> - Logger.info("GefsFetch: wrote #{count} scores for fh=#{fh} @ #{valid_time}") - broadcast_updated(valid_time) + _ = + case Propagation.replace_scores(scores, valid_time) do + {:ok, count} -> + Logger.info("GefsFetch: wrote #{count} scores for fh=#{fh} @ #{valid_time}") + broadcast_updated(valid_time) - error -> - Logger.error("GefsFetch: replace_scores failed fh=#{fh}: #{inspect(error)}") - end + error -> + Logger.error("GefsFetch: replace_scores failed fh=#{fh}: #{inspect(error)}") + end attrs = Enum.map(profiles, &build_profile_attrs(run_time, fh, &1)) {count, _} = Weather.upsert_gefs_profiles_batch(attrs) diff --git a/lib/microwaveprop/workers/iemre_fetch_worker.ex b/lib/microwaveprop/workers/iemre_fetch_worker.ex index 107a90b0..f7251bf1 100644 --- a/lib/microwaveprop/workers/iemre_fetch_worker.ex +++ b/lib/microwaveprop/workers/iemre_fetch_worker.ex @@ -30,17 +30,18 @@ defmodule Microwaveprop.Workers.IemreFetchWorker do case IemClient.fetch_iemre(lat, lon, date) do {:ok, []} -> # Store stub so this lat/lon/date isn't retried on future backfills - Weather.upsert_iemre_observation(%{lat: lat, lon: lon, date: date, hourly: []}) + _ = Weather.upsert_iemre_observation(%{lat: lat, lon: lon, date: date, hourly: []}) Logger.info("IEMRE: no data available for #{lat},#{lon} @ #{date_str}, stored stub") :ok {:ok, data} -> - Weather.upsert_iemre_observation(%{ - lat: lat, - lon: lon, - date: date, - hourly: data - }) + _ = + Weather.upsert_iemre_observation(%{ + lat: lat, + lon: lon, + date: date, + hourly: data + }) Logger.info("IEMRE observation saved for #{lat},#{lon} @ #{date_str} (#{length(data)} hours)") :ok diff --git a/lib/microwaveprop/workers/narr_fetch_worker.ex b/lib/microwaveprop/workers/narr_fetch_worker.ex index d74c0362..10a26be6 100644 --- a/lib/microwaveprop/workers/narr_fetch_worker.ex +++ b/lib/microwaveprop/workers/narr_fetch_worker.ex @@ -50,7 +50,7 @@ defmodule Microwaveprop.Workers.NarrFetchWorker do defp fetch_and_insert(rlat, rlon, valid_time) do case NarrClient.fetch_profile_at(valid_time, {rlat, rlon}) do {:ok, attrs} -> - insert_profile(attrs, rlat, rlon, valid_time) + _ = insert_profile(attrs, rlat, rlon, valid_time) :ok {:error, reason} = error -> diff --git a/lib/microwaveprop/workers/solar_index_worker.ex b/lib/microwaveprop/workers/solar_index_worker.ex index 25a619b7..965b63ef 100644 --- a/lib/microwaveprop/workers/solar_index_worker.ex +++ b/lib/microwaveprop/workers/solar_index_worker.ex @@ -17,13 +17,14 @@ defmodule Microwaveprop.Workers.SolarIndexWorker do matched = Enum.filter(all_records, fn r -> r.date == target_date end) Weather.upsert_solar_indices_batch(matched) - if matched != [] do - Phoenix.PubSub.broadcast( - Microwaveprop.PubSub, - "contact_enrichment:solar", - {:solar_ready, date_str} - ) - end + _ = + if matched != [] do + Phoenix.PubSub.broadcast( + Microwaveprop.PubSub, + "contact_enrichment:solar", + {:solar_ready, date_str} + ) + end :ok diff --git a/lib/microwaveprop/workers/terrain_profile_worker.ex b/lib/microwaveprop/workers/terrain_profile_worker.ex index 9dbccd9d..1500b8cf 100644 --- a/lib/microwaveprop/workers/terrain_profile_worker.ex +++ b/lib/microwaveprop/workers/terrain_profile_worker.ex @@ -20,7 +20,7 @@ defmodule Microwaveprop.Workers.TerrainProfileWorker do def perform(%Oban.Job{args: %{"contact_id" => contact_id}}) do Microwaveprop.Instrument.span([:worker, :terrain_profile], %{contact_id: contact_id}, fn -> if Terrain.has_terrain_profile?(contact_id) do - Radio.set_enrichment_status!([contact_id], :terrain_status, :complete) + _ = Radio.set_enrichment_status!([contact_id], :terrain_status, :complete) :ok else analyse_terrain(contact_id) @@ -38,7 +38,7 @@ defmodule Microwaveprop.Workers.TerrainProfileWorker do fetch_and_store_profile(contact_id, contact, lat1, lon1, lat2, lon2) else _ -> - Radio.set_enrichment_status!([contact_id], :terrain_status, :unavailable) + _ = Radio.set_enrichment_status!([contact_id], :terrain_status, :unavailable) :ok end end @@ -65,25 +65,27 @@ defmodule Microwaveprop.Workers.TerrainProfileWorker do %{"lat" => p.lat, "lon" => p.lon, "d" => p.d, "elev" => p.elev, "dist_km" => p.dist_km} end) - Terrain.upsert_terrain_profile(%{ - contact_id: contact_id, - sample_count: length(profile), - path_points: path_points, - max_elevation_m: analysis.max_elevation_m, - min_clearance_m: analysis.min_clearance_m, - diffraction_db: analysis.diffraction_db, - fresnel_hit_count: analysis.fresnel_hit_count, - obstructed_count: analysis.obstructed_count, - verdict: analysis.verdict - }) + _ = + Terrain.upsert_terrain_profile(%{ + contact_id: contact_id, + sample_count: length(profile), + path_points: path_points, + max_elevation_m: analysis.max_elevation_m, + min_clearance_m: analysis.min_clearance_m, + diffraction_db: analysis.diffraction_db, + fresnel_hit_count: analysis.fresnel_hit_count, + obstructed_count: analysis.obstructed_count, + verdict: analysis.verdict + }) - Radio.set_enrichment_status!([contact_id], :terrain_status, :complete) + _ = Radio.set_enrichment_status!([contact_id], :terrain_status, :complete) - Phoenix.PubSub.broadcast( - Microwaveprop.PubSub, - "contact_enrichment:#{contact_id}", - {:terrain_ready, contact_id} - ) + _ = + Phoenix.PubSub.broadcast( + Microwaveprop.PubSub, + "contact_enrichment:#{contact_id}", + {:terrain_ready, contact_id} + ) :ok end diff --git a/lib/microwaveprop/workers/weather_fetch_worker.ex b/lib/microwaveprop/workers/weather_fetch_worker.ex index 5edbb2fe..33d81326 100644 --- a/lib/microwaveprop/workers/weather_fetch_worker.ex +++ b/lib/microwaveprop/workers/weather_fetch_worker.ex @@ -96,11 +96,12 @@ defmodule Microwaveprop.Workers.WeatherFetchWorker do Logger.info("WeatherFetch ASOS: #{station_code} ingested #{count} observations") - Phoenix.PubSub.broadcast( - Microwaveprop.PubSub, - "contact_enrichment:weather", - {:weather_ready, %{station_id: station_id}} - ) + _ = + Phoenix.PubSub.broadcast( + Microwaveprop.PubSub, + "contact_enrichment:weather", + {:weather_ready, %{station_id: station_id}} + ) :ok end @@ -118,7 +119,7 @@ defmodule Microwaveprop.Workers.WeatherFetchWorker do defp fetch_raob(station, station_id, station_code, sounding_time, sounding_time_str, contact_id) do if Weather.has_sounding?(station.id, sounding_time) do Logger.debug("WeatherFetch RAOB: #{station_code} already has sounding for #{sounding_time_str}") - broadcast_sounding_fetched(station_id, contact_id) + _ = broadcast_sounding_fetched(station_id, contact_id) :ok else Logger.info("WeatherFetch RAOB: fetching #{station_code} for #{sounding_time_str}") @@ -132,9 +133,9 @@ defmodule Microwaveprop.Workers.WeatherFetchWorker do ingest_raob(station, station_id, station_code, parsed, contact_id) {:ok, []} -> - Weather.upsert_sounding(station, %{observed_at: sounding_time, profile: [], level_count: 0}) + _ = Weather.upsert_sounding(station, %{observed_at: sounding_time, profile: [], level_count: 0}) Logger.info("WeatherFetch RAOB: #{station_code} no data for #{sounding_time_str}, stored stub") - broadcast_sounding_fetched(station_id, contact_id) + _ = broadcast_sounding_fetched(station_id, contact_id) :ok {:error, reason} -> @@ -145,20 +146,21 @@ defmodule Microwaveprop.Workers.WeatherFetchWorker do defp ingest_raob(station, station_id, station_code, parsed, contact_id) do sounding_attrs = build_sounding_attrs(parsed) - Weather.upsert_sounding(station, sounding_attrs) + _ = Weather.upsert_sounding(station, sounding_attrs) Logger.info("WeatherFetch RAOB: #{station_code} ingested sounding with #{length(parsed.profile)} levels") - broadcast_sounding_fetched(station_id, contact_id) + _ = broadcast_sounding_fetched(station_id, contact_id) :ok end defp broadcast_sounding_fetched(station_id, contact_id) do - Phoenix.PubSub.broadcast( - Microwaveprop.PubSub, - "contact_enrichment:weather", - {:weather_ready, %{station_id: station_id}} - ) + _ = + Phoenix.PubSub.broadcast( + Microwaveprop.PubSub, + "contact_enrichment:weather", + {:weather_ready, %{station_id: station_id}} + ) if contact_id do Phoenix.PubSub.broadcast( diff --git a/lib/microwaveprop_web/controllers/health_controller.ex b/lib/microwaveprop_web/controllers/health_controller.ex index 3bbd6dbf..763f40ec 100644 --- a/lib/microwaveprop_web/controllers/health_controller.ex +++ b/lib/microwaveprop_web/controllers/health_controller.ex @@ -5,7 +5,7 @@ defmodule MicrowavepropWeb.HealthController do def check(conn, _params) do # Verify DB is reachable - SQL.query!(Microwaveprop.Repo, "SELECT 1") + _ = SQL.query!(Microwaveprop.Repo, "SELECT 1") conn |> put_resp_content_type("text/plain") diff --git a/lib/microwaveprop_web/controllers/user_reset_password_controller.ex b/lib/microwaveprop_web/controllers/user_reset_password_controller.ex index 8cd4bc90..8fa2a39b 100644 --- a/lib/microwaveprop_web/controllers/user_reset_password_controller.ex +++ b/lib/microwaveprop_web/controllers/user_reset_password_controller.ex @@ -10,13 +10,14 @@ defmodule MicrowavepropWeb.UserResetPasswordController do end def create(conn, %{"user" => %{"email" => email}}) do - if user = Accounts.get_user_by_email(email) do - {:ok, _email} = - Accounts.deliver_user_reset_password_instructions( - user, - &url(~p"/users/reset-password/#{&1}") - ) - end + _ = + if user = Accounts.get_user_by_email(email) do + {:ok, _email} = + Accounts.deliver_user_reset_password_instructions( + user, + &url(~p"/users/reset-password/#{&1}") + ) + end # Always respond the same way whether or not the email exists — this is # a deliberate anti-enumeration measure. If we redirected differently on diff --git a/lib/microwaveprop_web/controllers/user_settings_controller.ex b/lib/microwaveprop_web/controllers/user_settings_controller.ex index 887e1fe6..c721cc58 100644 --- a/lib/microwaveprop_web/controllers/user_settings_controller.ex +++ b/lib/microwaveprop_web/controllers/user_settings_controller.ex @@ -21,11 +21,12 @@ defmodule MicrowavepropWeb.UserSettingsController do case Accounts.change_user_email(user, user_params) do %{valid?: true} = changeset -> - Accounts.deliver_user_update_email_instructions( - Ecto.Changeset.apply_action!(changeset, :insert), - user.email, - &url(~p"/users/settings/confirm-email/#{&1}") - ) + _ = + Accounts.deliver_user_update_email_instructions( + Ecto.Changeset.apply_action!(changeset, :insert), + user.email, + &url(~p"/users/settings/confirm-email/#{&1}") + ) conn |> put_flash( diff --git a/lib/microwaveprop_web/live/admin/contact_edit_live.ex b/lib/microwaveprop_web/live/admin/contact_edit_live.ex index 8bf9cf74..d1da438d 100644 --- a/lib/microwaveprop_web/live/admin/contact_edit_live.ex +++ b/lib/microwaveprop_web/live/admin/contact_edit_live.ex @@ -73,7 +73,7 @@ defmodule MicrowavepropWeb.Admin.ContactEditLive do case Radio.approve_edit(edit, admin, note) do {:ok, approved} -> - EditNotifier.deliver_edit_approved(approved) + _ = EditNotifier.deliver_edit_approved(approved) {:noreply, socket @@ -93,7 +93,7 @@ defmodule MicrowavepropWeb.Admin.ContactEditLive do case Radio.reject_edit(edit, admin, note) do {:ok, rejected} -> - EditNotifier.deliver_edit_rejected(rejected) + _ = EditNotifier.deliver_edit_rejected(rejected) {:noreply, socket diff --git a/lib/microwaveprop_web/live/beacon_live/index.ex b/lib/microwaveprop_web/live/beacon_live/index.ex index 81ae1bbb..6154dd33 100644 --- a/lib/microwaveprop_web/live/beacon_live/index.ex +++ b/lib/microwaveprop_web/live/beacon_live/index.ex @@ -44,7 +44,7 @@ defmodule MicrowavepropWeb.BeaconLive.Index do @impl true def mount(_params, _session, socket) do - if connected?(socket), do: Beacons.subscribe_beacons() + _ = if connected?(socket), do: Beacons.subscribe_beacons() beacons = Beacons.list_beacons() diff --git a/lib/microwaveprop_web/live/beacon_live/show.ex b/lib/microwaveprop_web/live/beacon_live/show.ex index 5d2b8334..ad9a56f5 100644 --- a/lib/microwaveprop_web/live/beacon_live/show.ex +++ b/lib/microwaveprop_web/live/beacon_live/show.ex @@ -159,7 +159,7 @@ defmodule MicrowavepropWeb.BeaconLive.Show do @impl true def mount(%{"id" => id}, _session, socket) do - if connected?(socket), do: Beacons.subscribe_beacons() + _ = if connected?(socket), do: Beacons.subscribe_beacons() beacon = Beacons.get_beacon!(id) diff --git a/lib/microwaveprop_web/live/contact_live/show.ex b/lib/microwaveprop_web/live/contact_live/show.ex index 5b36cbe4..a48a02a6 100644 --- a/lib/microwaveprop_web/live/contact_live/show.ex +++ b/lib/microwaveprop_web/live/contact_live/show.ex @@ -81,7 +81,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do socket = if connected?(socket) do - Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "contact_enrichment:#{contact.id}") + :ok = Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "contact_enrichment:#{contact.id}") kickoff_hydration(socket, contact) else @@ -315,7 +315,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do if proposed == %{} do put_flash(socket, :error, "No changes detected.") else - Radio.apply_edit_to_contact(contact, proposed) + _ = Radio.apply_edit_to_contact(contact, proposed) updated = Radio.get_contact!(contact.id) socket @@ -387,7 +387,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do def handle_async(:solar, {:ok, solar}, socket) do solar = if socket.assigns.can_enqueue and is_nil(solar) do - enqueue_missing_solar(socket.assigns.contact) + _ = enqueue_missing_solar(socket.assigns.contact) nil else solar @@ -534,9 +534,10 @@ defmodule MicrowavepropWeb.ContactLive.Show do cond do has_data -> - if contact.weather_status != :complete do - Radio.set_enrichment_status!([contact.id], :weather_status, :complete) - end + _ = + if contact.weather_status != :complete do + Radio.set_enrichment_status!([contact.id], :weather_status, :complete) + end %{contact | weather_status: :complete} @@ -546,8 +547,8 @@ defmodule MicrowavepropWeb.ContactLive.Show do if jobs == [] do %{contact | weather_status: :unavailable} else - Oban.insert_all(jobs) - Radio.set_enrichment_status!([contact.id], :weather_status, :queued) + _ = Oban.insert_all(jobs) + _ = Radio.set_enrichment_status!([contact.id], :weather_status, :queued) %{contact | weather_status: :queued} end @@ -709,9 +710,10 @@ defmodule MicrowavepropWeb.ContactLive.Show do end defp maybe_enqueue_terrain(terrain, contact) when not is_nil(terrain) do - if contact.terrain_status != :complete do - Radio.set_enrichment_status!([contact.id], :terrain_status, :complete) - end + _ = + if contact.terrain_status != :complete do + Radio.set_enrichment_status!([contact.id], :terrain_status, :complete) + end %{contact | terrain_status: :complete} end @@ -721,7 +723,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do contact.pos1 && contact.pos2 && contact.terrain_status != :queued -> case Oban.insert(TerrainProfileWorker.new(%{"contact_id" => contact.id})) do {:ok, %{conflict?: false}} -> - Radio.set_enrichment_status!([contact.id], :terrain_status, :queued) + _ = Radio.set_enrichment_status!([contact.id], :terrain_status, :queued) %{contact | terrain_status: :queued} _ -> @@ -737,9 +739,10 @@ defmodule MicrowavepropWeb.ContactLive.Show do end defp maybe_enqueue_hrrr(hrrr, contact) when not is_nil(hrrr) do - if contact.hrrr_status != :complete do - Radio.set_enrichment_status!([contact.id], :hrrr_status, :complete) - end + _ = + if contact.hrrr_status != :complete do + Radio.set_enrichment_status!([contact.id], :hrrr_status, :complete) + end {hrrr, %{contact | hrrr_status: :complete}} end @@ -765,9 +768,10 @@ defmodule MicrowavepropWeb.ContactLive.Show do # Rust hrrr-point-worker picks them up alongside backfill work. {:ok, _} = HrrrPointEnqueuer.enqueue(%{valid_time => [{rlat, rlon}]}) - if contact.hrrr_status != :queued do - Radio.set_enrichment_status!([contact.id], :hrrr_status, :queued) - end + _ = + if contact.hrrr_status != :queued do + Radio.set_enrichment_status!([contact.id], :hrrr_status, :queued) + end {nil, %{contact | hrrr_status: :queued}} else @@ -785,15 +789,16 @@ defmodule MicrowavepropWeb.ContactLive.Show do lon = contact.pos1 && contact.pos1["lon"] valid_time = NarrClient.snap_to_analysis_hour(contact.qso_timestamp) - if lat && lon && NarrClient.in_coverage?(valid_time) do - %{ - "lat" => lat, - "lon" => lon, - "valid_time" => DateTime.to_iso8601(valid_time) - } - |> NarrFetchWorker.new() - |> Oban.insert() - end + _ = + if lat && lon && NarrClient.in_coverage?(valid_time) do + %{ + "lat" => lat, + "lon" => lon, + "valid_time" => DateTime.to_iso8601(valid_time) + } + |> NarrFetchWorker.new() + |> Oban.insert() + end contact end diff --git a/lib/microwaveprop_web/live/import_live.ex b/lib/microwaveprop_web/live/import_live.ex index 0dc8c44d..d563ab6f 100644 --- a/lib/microwaveprop_web/live/import_live.ex +++ b/lib/microwaveprop_web/live/import_live.ex @@ -23,9 +23,10 @@ defmodule MicrowavepropWeb.ImportLive do |> push_navigate(to: ~p"/submit")} %ImportRun{} = run -> - if connected?(socket) do - Phoenix.PubSub.subscribe(@pubsub, "csv_import:#{run.id}") - end + _ = + if connected?(socket) do + Phoenix.PubSub.subscribe(@pubsub, "csv_import:#{run.id}") + end {:ok, socket diff --git a/lib/microwaveprop_web/live/map_live.ex b/lib/microwaveprop_web/live/map_live.ex index 38ea78ed..3d57ce3a 100644 --- a/lib/microwaveprop_web/live/map_live.ex +++ b/lib/microwaveprop_web/live/map_live.ex @@ -35,12 +35,13 @@ defmodule MicrowavepropWeb.MapLive do @impl true def mount(params, session, socket) do - if connected?(socket) do - Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "propagation:updated") - Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "propagation:pipeline") - Process.send_after(self(), :refresh_pipeline_status, @pipeline_status_refresh_ms) - Process.send_after(self(), :advance_now_cursor, @advance_now_cursor_ms) - end + _ = + if connected?(socket) do + :ok = Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "propagation:updated") + :ok = Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "propagation:pipeline") + _ = Process.send_after(self(), :refresh_pipeline_status, @pipeline_status_refresh_ms) + _ = Process.send_after(self(), :advance_now_cursor, @advance_now_cursor_ms) + end socket = socket diff --git a/lib/microwaveprop_web/live/path_live.ex b/lib/microwaveprop_web/live/path_live.ex index c7f8f658..820e1105 100644 --- a/lib/microwaveprop_web/live/path_live.ex +++ b/lib/microwaveprop_web/live/path_live.ex @@ -33,9 +33,10 @@ defmodule MicrowavepropWeb.PathLive do @impl true def mount(_params, _session, socket) do - if connected?(socket) do - Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "propagation:updated") - end + _ = + if connected?(socket) do + Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "propagation:updated") + end {:ok, assign(socket, diff --git a/lib/microwaveprop_web/live/rover_live.ex b/lib/microwaveprop_web/live/rover_live.ex index f68e4c27..1744007e 100644 --- a/lib/microwaveprop_web/live/rover_live.ex +++ b/lib/microwaveprop_web/live/rover_live.ex @@ -22,9 +22,10 @@ defmodule MicrowavepropWeb.RoverLive do @impl true def mount(_params, _session, socket) do - if connected?(socket) do - Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "propagation:updated") - end + _ = + if connected?(socket) do + Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "propagation:updated") + end initial_scores = Propagation.latest_scores(@default_band, @initial_bounds) diff --git a/lib/microwaveprop_web/live/status_live.ex b/lib/microwaveprop_web/live/status_live.ex index f3dc2c5b..cd758f73 100644 --- a/lib/microwaveprop_web/live/status_live.ex +++ b/lib/microwaveprop_web/live/status_live.ex @@ -11,15 +11,16 @@ defmodule MicrowavepropWeb.StatusLive do @impl true def mount(_params, _session, socket) do - if connected?(socket) do - Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "db:contact_status") - Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "db:oban_jobs") - # Rust prop-grid-rs emits NOTIFY propagation_ready on completion — - # PropagationNotifyListener fans it out as `propagation:updated` so - # the grid_tasks panel transitions from "running" → "done" without - # a manual refresh. - Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "propagation:updated") - end + _ = + if connected?(socket) do + :ok = Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "db:contact_status") + :ok = Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "db:oban_jobs") + # Rust prop-grid-rs emits NOTIFY propagation_ready on completion — + # PropagationNotifyListener fans it out as `propagation:updated` so + # the grid_tasks panel transitions from "running" → "done" without + # a manual refresh. + Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "propagation:updated") + end stats = fetch_stats() unprocessed = count_unprocessed() diff --git a/lib/microwaveprop_web/live/weather_map_live.ex b/lib/microwaveprop_web/live/weather_map_live.ex index ecd78813..1b98a2a5 100644 --- a/lib/microwaveprop_web/live/weather_map_live.ex +++ b/lib/microwaveprop_web/live/weather_map_live.ex @@ -138,10 +138,11 @@ defmodule MicrowavepropWeb.WeatherMapLive do @impl true def mount(_params, _session, socket) do - if connected?(socket) do - Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "weather:updated") - Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "propagation:pipeline") - end + _ = + if connected?(socket) do + :ok = Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "weather:updated") + Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "propagation:pipeline") + end # Default the timeline cursor to the valid_time closest to "now" so # users land on current conditions, not a +11h forecast hour (which diff --git a/lib/microwaveprop_web/user_auth.ex b/lib/microwaveprop_web/user_auth.ex index 56c64951..9d852921 100644 --- a/lib/microwaveprop_web/user_auth.ex +++ b/lib/microwaveprop_web/user_auth.ex @@ -91,9 +91,10 @@ defmodule MicrowavepropWeb.UserAuth do user_token = get_session(conn, :user_token) user_token && Accounts.delete_user_session_token(user_token) - if live_socket_id = get_session(conn, :live_socket_id) do - MicrowavepropWeb.Endpoint.broadcast(live_socket_id, "disconnect", %{}) - end + _ = + if live_socket_id = get_session(conn, :live_socket_id) do + MicrowavepropWeb.Endpoint.broadcast(live_socket_id, "disconnect", %{}) + end conn |> renew_session(nil) diff --git a/lib/mix/tasks/backtest.ex b/lib/mix/tasks/backtest.ex index 08a873e3..223ff67c 100644 --- a/lib/mix/tasks/backtest.ex +++ b/lib/mix/tasks/backtest.ex @@ -34,7 +34,7 @@ defmodule Mix.Tasks.Backtest do @impl Mix.Task def run(argv) do Mix.Task.run("app.start") - Oban.pause_all_queues(Oban) + _ = Oban.pause_all_queues(Oban) {opts, _, _} = OptionParser.parse(argv, diff --git a/lib/mix/tasks/hrrr_backfill.ex b/lib/mix/tasks/hrrr_backfill.ex index 547d498e..4ba9874f 100644 --- a/lib/mix/tasks/hrrr_backfill.ex +++ b/lib/mix/tasks/hrrr_backfill.ex @@ -28,7 +28,7 @@ defmodule Mix.Tasks.HrrrBackfill do @impl Mix.Task def run(args) do Mix.Task.run("app.start") - Oban.pause_all_queues(Oban) + _ = Oban.pause_all_queues(Oban) {opts, _, _} = OptionParser.parse(args, switches: [all: :boolean, limit: :integer]) refetch_all? = Keyword.get(opts, :all, false) diff --git a/lib/mix/tasks/hrrr_climatology.ex b/lib/mix/tasks/hrrr_climatology.ex index 40edcdcd..c418f923 100644 --- a/lib/mix/tasks/hrrr_climatology.ex +++ b/lib/mix/tasks/hrrr_climatology.ex @@ -17,7 +17,7 @@ defmodule Mix.Tasks.HrrrClimatology do @impl Mix.Task def run(argv) do Mix.Task.run("app.start") - Oban.pause_all_queues(Oban) + _ = Oban.pause_all_queues(Oban) {opts, _, _} = OptionParser.parse(argv, switches: [min_samples: :integer]) min_samples = Keyword.get(opts, :min_samples, 3) diff --git a/lib/mix/tasks/hrrr_native_backfill.ex b/lib/mix/tasks/hrrr_native_backfill.ex index 8f5e9a70..88013967 100644 --- a/lib/mix/tasks/hrrr_native_backfill.ex +++ b/lib/mix/tasks/hrrr_native_backfill.ex @@ -26,7 +26,7 @@ defmodule Mix.Tasks.HrrrNativeBackfill do @impl Mix.Task def run(argv) do Mix.Task.run("app.start") - Oban.pause_all_queues(Oban) + _ = Oban.pause_all_queues(Oban) {opts, _, _} = OptionParser.parse(argv, switches: [limit: :integer]) limit = Keyword.get(opts, :limit, 50) diff --git a/lib/mix/tasks/hrrr_native_derive.ex b/lib/mix/tasks/hrrr_native_derive.ex index 0545cfa1..49db0ac8 100644 --- a/lib/mix/tasks/hrrr_native_derive.ex +++ b/lib/mix/tasks/hrrr_native_derive.ex @@ -23,7 +23,7 @@ defmodule Mix.Tasks.HrrrNativeDeriveFields do @impl Mix.Task def run(argv) do Mix.Task.run("app.start") - Oban.pause_all_queues(Oban) + _ = Oban.pause_all_queues(Oban) {opts, _, _} = OptionParser.parse(argv, switches: [limit: :integer]) limit = Keyword.get(opts, :limit, 10_000) diff --git a/lib/mix/tasks/import_contest_logs.ex b/lib/mix/tasks/import_contest_logs.ex index bac4843d..a3e89e50 100644 --- a/lib/mix/tasks/import_contest_logs.ex +++ b/lib/mix/tasks/import_contest_logs.ex @@ -21,7 +21,7 @@ defmodule Mix.Tasks.ImportContestLogs do end Mix.Task.run("app.start") - Oban.pause_all_queues(Oban) + _ = Oban.pause_all_queues(Oban) # Concatenate all CSVs into one string (skip headers after the first file) combined = diff --git a/lib/mix/tasks/nexrad_backfill.ex b/lib/mix/tasks/nexrad_backfill.ex index 291b53ef..d2f6f766 100644 --- a/lib/mix/tasks/nexrad_backfill.ex +++ b/lib/mix/tasks/nexrad_backfill.ex @@ -24,7 +24,7 @@ defmodule Mix.Tasks.NexradBackfill do @impl Mix.Task def run(argv) do Mix.Task.run("app.start") - Oban.pause_all_queues(Oban) + _ = Oban.pause_all_queues(Oban) {opts, _, _} = OptionParser.parse(argv, switches: [limit: :integer]) limit = Keyword.get(opts, :limit, 200) diff --git a/lib/mix/tasks/propagation_grid.ex b/lib/mix/tasks/propagation_grid.ex index 5ca97c61..ee73a79e 100644 --- a/lib/mix/tasks/propagation_grid.ex +++ b/lib/mix/tasks/propagation_grid.ex @@ -23,7 +23,7 @@ defmodule Mix.Tasks.PropagationGrid do IO.puts("Starting propagation grid computation...") - PropagationGridWorker.perform(%Oban.Job{args: %{}}) + _ = PropagationGridWorker.perform(%Oban.Job{args: %{}}) IO.puts("Done!") end end diff --git a/lib/mix/tasks/radar_backfill.ex b/lib/mix/tasks/radar_backfill.ex index 76b07a29..caba0ef1 100644 --- a/lib/mix/tasks/radar_backfill.ex +++ b/lib/mix/tasks/radar_backfill.ex @@ -57,8 +57,8 @@ defmodule Mix.Tasks.RadarBackfill do |> Enum.with_index(1) |> Enum.each(fn {batch, i} -> jobs = Enum.map(batch, &CommonVolumeRadarWorker.new(%{"contact_id" => &1})) - Oban.insert_all(jobs) - Radio.set_enrichment_status!(batch, :radar_status, :queued) + _ = Oban.insert_all(jobs) + _ = Radio.set_enrichment_status!(batch, :radar_status, :queued) Mix.shell().info(" batch #{i}: #{length(batch)} enqueued") end) diff --git a/lib/mix/tasks/recalibrate_scorer.ex b/lib/mix/tasks/recalibrate_scorer.ex index 1efe08bd..a345f3d9 100644 --- a/lib/mix/tasks/recalibrate_scorer.ex +++ b/lib/mix/tasks/recalibrate_scorer.ex @@ -25,7 +25,7 @@ defmodule Mix.Tasks.RecalibrateScorer do @impl Mix.Task def run(argv) do Mix.Task.run("app.start") - Oban.pause_all_queues(Oban) + _ = Oban.pause_all_queues(Oban) {opts, _, _} = OptionParser.parse(argv, diff --git a/lib/mix/tasks/reset_enrichment.ex b/lib/mix/tasks/reset_enrichment.ex index 0047c893..c27a03e0 100644 --- a/lib/mix/tasks/reset_enrichment.ex +++ b/lib/mix/tasks/reset_enrichment.ex @@ -21,7 +21,7 @@ defmodule Mix.Tasks.ResetEnrichment do @impl Mix.Task def run(_args) do Mix.Task.run("app.start") - Oban.pause_all_queues(Oban) + _ = Oban.pause_all_queues(Oban) {count, _} = Contact diff --git a/lib_ml/propagation_analyze.ex b/lib_ml/propagation_analyze.ex index 0ae44517..8a784bf7 100644 --- a/lib_ml/propagation_analyze.ex +++ b/lib_ml/propagation_analyze.ex @@ -239,13 +239,14 @@ defmodule Mix.Tasks.PropagationAnalyze do end) |> Enum.sort_by(fn {_, rho, _} -> -abs(rho || 0) end) - for {label, rho, n} <- correlations do - rho_str = if rho, do: format_num(rho, 4), else: "N/A" + _ = + for {label, rho, n} <- correlations do + rho_str = if rho, do: format_num(rho, 4), else: "N/A" - IO.puts( - " #{String.pad_trailing(label, 28)} #{String.pad_leading(rho_str, 8)} #{String.pad_leading(Integer.to_string(n), 8)}" - ) - end + IO.puts( + " #{String.pad_trailing(label, 28)} #{String.pad_leading(rho_str, 8)} #{String.pad_leading(Integer.to_string(n), 8)}" + ) + end end IO.puts("") @@ -353,11 +354,12 @@ defmodule Mix.Tasks.PropagationAnalyze do IO.puts("\n#{format_band(band)} (n=#{length(band_data)}):") - for {key, label, bins} <- factor_configs do - print_binned_factor(band_data, key, label, bins) - end + _ = + for {key, label, bins} <- factor_configs do + _ = print_binned_factor(band_data, key, label, bins) + end - print_categorical_factor(band_data, terrain_config) + _ = print_categorical_factor(band_data, terrain_config) end IO.puts("") diff --git a/lib_ml/propagation_train.ex b/lib_ml/propagation_train.ex index 6107e8b5..0addde6c 100644 --- a/lib_ml/propagation_train.ex +++ b/lib_ml/propagation_train.ex @@ -102,7 +102,7 @@ defmodule Mix.Tasks.PropagationTrain do Model.save(trained_state) IO.puts("Done.") - check_monthly_bias(trained_state) + _ = check_monthly_bias(trained_state) "-" |> String.duplicate(70) |> IO.puts() IO.puts("Finished: #{DateTime.to_string(DateTime.utc_now())}") diff --git a/mix.exs b/mix.exs index 66353b9c..40f8848b 100644 --- a/mix.exs +++ b/mix.exs @@ -21,7 +21,8 @@ defmodule Microwaveprop.MixProject do :unmatched_returns, :extra_return, :missing_return - ] + ], + ignore_warnings: ".dialyzer_ignore.exs" ] ] end