diff --git a/.dialyzer_ignore.exs b/.dialyzer_ignore.exs index c17c9a01..53b7ff70 100644 --- a/.dialyzer_ignore.exs +++ b/.dialyzer_ignore.exs @@ -1,24 +1,3 @@ -# Dialyzer warnings to ignore -# These are either false positives or intentional design choices -[ - # SnmpKit library warnings (third-party code in lib/snmpkit/) - ~r/lib\/snmpkit\//, - - # Unmatched return values (intentionally ignored for fire-and-forget operations) - {"lib/towerops/agents.ex", :unmatched_return}, - {"lib/towerops/devices.ex", :unmatched_return}, - {"lib/towerops/workers/agent_latency_evaluator.ex", :unmatched_return}, - {"lib/towerops/workers/device_monitor_worker.ex", :unmatched_return}, - {"lib/towerops/workers/device_poller_worker.ex", :unmatched_return}, - {"lib/towerops/workers/stale_agent_worker.ex", :unmatched_return}, - {"lib/towerops_web/channels/agent_channel.ex", :unmatched_return}, - {"lib/towerops_web/live/device_live/form.ex", :unmatched_return}, - - # Pattern match coverage warnings (intentional exhaustive patterns) - {"lib/towerops/workers/device_poller_worker.ex", :pattern_match_cov}, - {"lib/towerops_web/channels/agent_channel.ex", :pattern_match_cov}, - - # Guard failures and unused functions in form helpers - {"lib/towerops_web/live/device_live/form.ex", :guard_fail}, - {"lib/towerops_web/live/device_live/form.ex", :unused_fun} -] +# Dialyzer false positives to ignore +# Fix all warnings - do not suppress +[] diff --git a/lib/towerops/agents.ex b/lib/towerops/agents.ex index e63d96eb..973bbf65 100644 --- a/lib/towerops/agents.ex +++ b/lib/towerops/agents.ex @@ -294,7 +294,7 @@ defmodule Towerops.Agents do case result do {:ok, assignment} -> - broadcast_assignment_change(agent_token_id, :device_assigned) + _ = broadcast_assignment_change(agent_token_id, :device_assigned) {:ok, assignment} error -> @@ -321,9 +321,10 @@ defmodule Towerops.Agents do |> Repo.delete_all() # Notify the agent that was previously assigned - if current_assignment do - broadcast_assignment_change(current_assignment.agent_token_id, :device_unassigned) - end + _ = + if current_assignment do + broadcast_assignment_change(current_assignment.agent_token_id, :device_unassigned) + end result end @@ -466,10 +467,11 @@ defmodule Towerops.Agents do case result do {:ok, assignment} -> # Notify both the old and new agents if they're different - if old_agent_id != agent_token_id do - broadcast_assignment_change(old_agent_id, :device_unassigned) - broadcast_assignment_change(agent_token_id, :device_assigned) - end + _ = + if old_agent_id != agent_token_id do + _ = broadcast_assignment_change(old_agent_id, :device_unassigned) + broadcast_assignment_change(agent_token_id, :device_assigned) + end {:ok, assignment} diff --git a/lib/towerops/devices.ex b/lib/towerops/devices.ex index 3f0070e9..c07a1ff6 100644 --- a/lib/towerops/devices.ex +++ b/lib/towerops/devices.ex @@ -259,13 +259,15 @@ defmodule Towerops.Devices do |> Repo.insert() do {:ok, device} = result -> # Start monitoring/polling if enabled - if device.monitoring_enabled do - DeviceMonitorWorker.start_monitoring(device.id) - end + _ = + if device.monitoring_enabled do + DeviceMonitorWorker.start_monitoring(device.id) + end - if device.snmp_enabled do - DevicePollerWorker.start_polling(device.id) - end + _ = + if device.snmp_enabled do + DevicePollerWorker.start_polling(device.id) + end result @@ -285,8 +287,8 @@ defmodule Towerops.Devices do |> DeviceSchema.changeset(attrs) |> Repo.update() do {:ok, updated_device} = result -> - handle_monitoring_changes(updated_device, old_monitoring) - handle_snmp_changes(updated_device, old_snmp) + _ = handle_monitoring_changes(updated_device, old_monitoring) + _ = handle_snmp_changes(updated_device, old_snmp) result error -> diff --git a/lib/towerops/workers/agent_latency_evaluator.ex b/lib/towerops/workers/agent_latency_evaluator.ex index 0d5510df..3d3d56f4 100644 --- a/lib/towerops/workers/agent_latency_evaluator.ex +++ b/lib/towerops/workers/agent_latency_evaluator.ex @@ -80,7 +80,7 @@ defmodule Towerops.Workers.AgentLatencyEvaluator do case result do {:ok, _} -> - broadcast_reassignment(candidate) + _ = broadcast_reassignment(candidate) :ok {:error, reason} -> diff --git a/lib/towerops/workers/device_monitor_worker.ex b/lib/towerops/workers/device_monitor_worker.ex index 512f3f4f..a2bad7f5 100644 --- a/lib/towerops/workers/device_monitor_worker.ex +++ b/lib/towerops/workers/device_monitor_worker.ex @@ -33,12 +33,21 @@ defmodule Towerops.Workers.DeviceMonitorWorker do :ok device -> - if device.monitoring_enabled do - perform_check(device) - end + _ = + if device.monitoring_enabled do + perform_check(device) + end # Schedule next check - schedule_next_check(device_id) + case schedule_next_check(device_id) do + {:ok, _job} -> + :ok + + {:error, changeset} -> + Logger.error("Failed to schedule next monitoring check for device #{device_id}: #{inspect(changeset.errors)}") + + :ok + end :ok end @@ -108,16 +117,18 @@ defmodule Towerops.Workers.DeviceMonitorWorker do _ = Devices.update_device_status(device, new_status) - if old_status != new_status do - handle_status_change(device, old_status, new_status) - end + _ = + if old_status != new_status do + handle_status_change(device, old_status, new_status) + end # Broadcast status change via PubSub - Phoenix.PubSub.broadcast( - Towerops.PubSub, - "device:#{device.id}", - {:device_status_changed, device.id, new_status, nil} - ) + _ = + Phoenix.PubSub.broadcast( + Towerops.PubSub, + "device:#{device.id}", + {:device_status_changed, device.id, new_status, nil} + ) end defp check_device_health(device) do @@ -155,11 +166,12 @@ defmodule Towerops.Workers.DeviceMonitorWorker do message: alert_message }) - Phoenix.PubSub.broadcast( - Towerops.PubSub, - "alerts:new", - {:new_alert, device.id, :device_down} - ) + _ = + Phoenix.PubSub.broadcast( + Towerops.PubSub, + "alerts:new", + {:new_alert, device.id, :device_down} + ) end defp get_down_alert_message(device) do @@ -183,11 +195,12 @@ defmodule Towerops.Workers.DeviceMonitorWorker do resolve_down_alert(device) - Phoenix.PubSub.broadcast( - Towerops.PubSub, - "alerts:resolved", - {:alert_resolved, device.id, :device_down} - ) + _ = + Phoenix.PubSub.broadcast( + Towerops.PubSub, + "alerts:resolved", + {:alert_resolved, device.id, :device_down} + ) end defp get_recovery_message(device) do diff --git a/lib/towerops/workers/device_poller_worker.ex b/lib/towerops/workers/device_poller_worker.ex index 3896c79b..be8828e9 100644 --- a/lib/towerops/workers/device_poller_worker.ex +++ b/lib/towerops/workers/device_poller_worker.ex @@ -45,7 +45,16 @@ defmodule Towerops.Workers.DevicePollerWorker do # Schedule next poll poll_interval = get_poll_interval(device) - schedule_next_poll(device_id, poll_interval) + + case schedule_next_poll(device_id, poll_interval) do + {:ok, _job} -> + :ok + + {:error, changeset} -> + Logger.error("Failed to schedule next poll for device #{device_id}: #{inspect(changeset.errors)}") + + :ok + end :ok end @@ -136,11 +145,12 @@ defmodule Towerops.Workers.DevicePollerWorker do poll_sensors(snmp_device.sensors, client_opts, now) Logger.debug("Polled #{length(snmp_device.sensors)} sensors for #{device.name}") - Phoenix.PubSub.broadcast( - Towerops.PubSub, - "device:#{device.id}", - {:sensors_updated, device.id} - ) + _ = + Phoenix.PubSub.broadcast( + Towerops.PubSub, + "device:#{device.id}", + {:sensors_updated, device.id} + ) rescue error -> Logger.error("Error polling sensors for #{device.name}: #{inspect(error)}\n#{Exception.format_stacktrace()}") @@ -150,11 +160,12 @@ defmodule Towerops.Workers.DevicePollerWorker do poll_state_sensors(snmp_device.state_sensors, client_opts, now, device.id) Logger.debug("Polled #{length(snmp_device.state_sensors)} state sensors for #{device.name}") - Phoenix.PubSub.broadcast( - Towerops.PubSub, - "device:#{device.id}", - {:state_sensors_updated, device.id} - ) + _ = + Phoenix.PubSub.broadcast( + Towerops.PubSub, + "device:#{device.id}", + {:state_sensors_updated, device.id} + ) rescue error -> Logger.error("Error polling state sensors for #{device.name}: #{inspect(error)}\n#{Exception.format_stacktrace()}") @@ -164,11 +175,12 @@ defmodule Towerops.Workers.DevicePollerWorker do poll_interfaces(snmp_device.interfaces, client_opts, now) Logger.debug("Polled #{length(snmp_device.interfaces)} interfaces for #{device.name}") - Phoenix.PubSub.broadcast( - Towerops.PubSub, - "device:#{device.id}", - {:interfaces_updated, device.id} - ) + _ = + Phoenix.PubSub.broadcast( + Towerops.PubSub, + "device:#{device.id}", + {:interfaces_updated, device.id} + ) rescue error -> Logger.error("Error polling interfaces for #{device.name}: #{inspect(error)}\n#{Exception.format_stacktrace()}") @@ -197,11 +209,12 @@ defmodule Towerops.Workers.DevicePollerWorker do Logger.debug("Polled and saved #{length(neighbors)} neighbors for #{device.name}") - Phoenix.PubSub.broadcast( - Towerops.PubSub, - "device:#{device.id}", - {:neighbors_updated, device.id} - ) + _ = + Phoenix.PubSub.broadcast( + Towerops.PubSub, + "device:#{device.id}", + {:neighbors_updated, device.id} + ) rescue error -> Logger.error("Error polling neighbors for #{device.name}: #{inspect(error)}\n#{Exception.format_stacktrace()}") @@ -217,11 +230,12 @@ defmodule Towerops.Workers.DevicePollerWorker do Logger.debug("Polled and saved #{length(arp_entries)} ARP entries for #{device.name}") - Phoenix.PubSub.broadcast( - Towerops.PubSub, - "device:#{device.id}", - {:arp_updated, device.id} - ) + _ = + Phoenix.PubSub.broadcast( + Towerops.PubSub, + "device:#{device.id}", + {:arp_updated, device.id} + ) rescue error -> Logger.error("Error polling ARP table for #{device.name}: #{inspect(error)}\n#{Exception.format_stacktrace()}") @@ -237,11 +251,12 @@ defmodule Towerops.Workers.DevicePollerWorker do Logger.debug("Polled and saved #{length(mac_entries)} MAC FDB entries for #{device.name}") - Phoenix.PubSub.broadcast( - Towerops.PubSub, - "device:#{device.id}", - {:mac_updated, device.id} - ) + _ = + Phoenix.PubSub.broadcast( + Towerops.PubSub, + "device:#{device.id}", + {:mac_updated, device.id} + ) rescue error -> Logger.error("Error polling MAC FDB table for #{device.name}: #{inspect(error)}\n#{Exception.format_stacktrace()}") @@ -254,11 +269,12 @@ defmodule Towerops.Workers.DevicePollerWorker do poll_processors(processors, client_opts, now) Logger.debug("Polled processors for #{device.name}") - Phoenix.PubSub.broadcast( - Towerops.PubSub, - "device:#{device.id}", - {:processors_updated, device.id} - ) + _ = + Phoenix.PubSub.broadcast( + Towerops.PubSub, + "device:#{device.id}", + {:processors_updated, device.id} + ) end rescue error -> @@ -272,11 +288,12 @@ defmodule Towerops.Workers.DevicePollerWorker do poll_storage(storage_entries, client_opts, now) Logger.debug("Polled #{length(storage_entries)} storage entries for #{device.name}") - Phoenix.PubSub.broadcast( - Towerops.PubSub, - "device:#{device.id}", - {:storage_updated, device.id} - ) + _ = + Phoenix.PubSub.broadcast( + Towerops.PubSub, + "device:#{device.id}", + {:storage_updated, device.id} + ) end rescue error -> @@ -318,7 +335,6 @@ defmodule Towerops.Workers.DevicePollerWorker do else {:error, reason} -> {:error, reason} false -> {:error, :invalid_values} - _ -> {:error, :unknown} end end diff --git a/lib/towerops/workers/stale_agent_worker.ex b/lib/towerops/workers/stale_agent_worker.ex index e70458c4..bace4e14 100644 --- a/lib/towerops/workers/stale_agent_worker.ex +++ b/lib/towerops/workers/stale_agent_worker.ex @@ -31,9 +31,10 @@ defmodule Towerops.Workers.StaleAgentWorker do def perform(%Oban.Job{}) do stale_agents = find_stale_agents() - if !Enum.empty?(stale_agents) do - process_stale_agents(stale_agents) - end + _ = + if !Enum.empty?(stale_agents) do + process_stale_agents(stale_agents) + end :ok end @@ -50,7 +51,7 @@ defmodule Towerops.Workers.StaleAgentWorker do Enum.each(long_term_stale, fn agent -> log_stale_agent(agent, :debug) end) # Broadcast all stale agents for UI updates - Phoenix.PubSub.broadcast(Towerops.PubSub, "agents:health", {:agents_stale, stale_agents}) + _ = Phoenix.PubSub.broadcast(Towerops.PubSub, "agents:health", {:agents_stale, stale_agents}) end defp log_newly_stale_agents([]), do: :ok diff --git a/lib/towerops_web/channels/agent_channel.ex b/lib/towerops_web/channels/agent_channel.ex index 2ed5638c..8e14f5cd 100644 --- a/lib/towerops_web/channels/agent_channel.ex +++ b/lib/towerops_web/channels/agent_channel.ex @@ -50,7 +50,7 @@ defmodule ToweropsWeb.AgentChannel do |> assign(:organization_id, agent_token.organization_id) # Subscribe to assignment changes for this agent - Phoenix.PubSub.subscribe(Towerops.PubSub, "agent:#{agent_token.id}:assignments") + _ = Phoenix.PubSub.subscribe(Towerops.PubSub, "agent:#{agent_token.id}:assignments") # Update last_seen_at and IP on join remote_ip = get_remote_ip(socket) @@ -463,7 +463,7 @@ defmodule ToweropsWeb.AgentChannel do pid when is_pid(pid) -> case :ranch.get_addr(pid) do - {ip, _port} -> format_ip(ip) + {ip, _port} when is_tuple(ip) -> format_ip(ip) _ -> nil end end @@ -476,6 +476,4 @@ defmodule ToweropsWeb.AgentChannel do defp format_ip({a, b, c, d, e, f, g, h}), do: "#{Integer.to_string(a, 16)}:#{Integer.to_string(b, 16)}:#{Integer.to_string(c, 16)}:#{Integer.to_string(d, 16)}:#{Integer.to_string(e, 16)}:#{Integer.to_string(f, 16)}:#{Integer.to_string(g, 16)}:#{Integer.to_string(h, 16)}" - - defp format_ip(_), do: nil end diff --git a/lib/towerops_web/live/device_live/form.ex b/lib/towerops_web/live/device_live/form.ex index d0ab086b..9452368f 100644 --- a/lib/towerops_web/live/device_live/form.ex +++ b/lib/towerops_web/live/device_live/form.ex @@ -314,9 +314,10 @@ defmodule ToweropsWeb.DeviceLive.Form do "Device created. " end - if device.snmp_enabled do - _ = enqueue_discovery(device.id) - end + _ = + if device.snmp_enabled do + enqueue_discovery(device.id) + end %{ text: base_message, @@ -540,11 +541,9 @@ defmodule ToweropsWeb.DeviceLive.Form do end end - @dev_env Mix.env() == :dev - defp skip_non_routable_check?(assigns) do # Skip in dev mode or for specific users - @dev_env || + Application.get_env(:towerops, :env) == :dev || (assigns[:current_scope] && assigns.current_scope.user && assigns.current_scope.user.email == "graham@mcintire.me") end