defmodule Microwaveprop.Commercial.PollWorker do @moduledoc false use Oban.Worker, queue: :commercial, max_attempts: 1 alias Microwaveprop.Commercial alias Microwaveprop.Commercial.SnmpClient alias Microwaveprop.Weather alias Microwaveprop.Weather.IemClient require Logger @impl Oban.Worker def perform(%Oban.Job{}) do links = Commercial.enabled_links() poll_and_record(links, &SnmpClient.poll/3) fetch_weather(links) :ok end def poll_and_record(links, poll_fn) do now = DateTime.utc_now() Enum.each(links, fn link -> case poll_fn.(link.host, link.community, link.radio_type) do {:ok, data} -> attrs = data |> Map.put(:link_id, link.id) |> Map.put(:sampled_at, now) case Commercial.create_sample(attrs) do {:ok, _sample} -> Logger.info("Recorded sample for #{link.label}") {:error, changeset} -> Logger.warning("Failed to save sample for #{link.label}: #{inspect(changeset.errors)}") end {:error, reason} -> Logger.warning("SNMP poll failed for #{link.label} (#{link.host}): #{inspect(reason)}") end end) end defp fetch_weather(links) do stations = links |> Enum.map(& &1.weather_station) |> Enum.reject(&is_nil/1) |> Enum.uniq() now = DateTime.utc_now() start_dt = DateTime.add(now, -3600, :second) Enum.each(stations, fn station_code -> {:ok, station} = Weather.find_or_create_station(%{ station_code: station_code, station_type: "asos", name: station_code, lat: 0.0, lon: 0.0 }) case IemClient.fetch_asos(station_code, start_dt, now) do {:ok, rows} -> Enum.each(rows, fn row -> if row.observed_at, do: Weather.upsert_surface_observation(station, row) end) Logger.info("Fetched #{length(rows)} ASOS observations for #{station_code}") {:error, reason} -> Logger.warning("ASOS fetch failed for #{station_code}: #{inspect(reason)}") end end) end end