towerops/lib/towerops/workers/monitor_worker.ex
Graham McIntire 0a4482f974
feat: add 5 new vendor modules and fix dialyzer issues
Vendor modules added:
- Aviat (WTM microwave radios)
- Aruba (wireless controllers and APs)
- CiscoWLC (Cisco wireless LAN controllers)
- Teltonika (RUTOS LTE routers)
- Sub10 (mmWave backhaul radios)

Dialyzer fixes:
- Fix unknown type Devices.t/0 in alert.ex and device.ex
- Fix unmatched_return warnings across multiple files
- Add :exq to PLT for Exq function detection
- Remove dead code in base.ex, dynamic.ex, vendor.ex
- Fix Device.t() type spec to allow nil name field

Tests: 1437 tests, 0 failures
Dialyzer: 0 errors
Credo: no issues
2026-01-22 09:34:50 -06:00

96 lines
2.5 KiB
Elixir

defmodule Towerops.Workers.MonitorWorker do
@moduledoc """
Background worker for device monitoring checks (ICMP pings).
Enqueued when:
- trigger_check is called but the DeviceMonitor GenServer doesn't exist
- Manual monitoring check trigger from UI
Queue: monitoring
"""
alias Towerops.Devices
alias Towerops.Monitoring
require Logger
defp ping_adapter do
Application.get_env(:towerops, :ping_module, Towerops.Monitoring.Ping)
end
@doc """
Performs a monitoring check for a device.
## Parameters
- device_id: The UUID of the device to check
## Returns
- :ok on success
- {:error, reason} on failure
"""
def perform(device_id) do
Logger.info("Starting monitoring check for device #{device_id}")
device = Devices.get_device!(device_id)
if device.monitoring_enabled do
case ping_device(device) do
{:ok, latency} ->
Logger.debug("Device #{device_id} is up, latency: #{latency}ms")
Monitoring.create_check(%{
device_id: device_id,
status: :success,
response_time_ms: latency,
checked_at: DateTime.utc_now()
})
# Broadcast monitoring check update to device-specific topic
_ =
Phoenix.PubSub.broadcast(
Towerops.PubSub,
"device:#{device_id}",
{:monitoring_check_updated, device_id}
)
:ok
{:error, reason} ->
Logger.warning("Device #{device_id} is down: #{inspect(reason)}")
Monitoring.create_check(%{
device_id: device_id,
status: :failure,
response_time_ms: nil,
checked_at: DateTime.utc_now()
})
# Broadcast monitoring check update to device-specific topic
_ =
Phoenix.PubSub.broadcast(
Towerops.PubSub,
"device:#{device_id}",
{:monitoring_check_updated, device_id}
)
:ok
end
else
Logger.debug("Device #{device_id} does not have monitoring enabled, skipping check")
:ok
end
rescue
Ecto.NoResultsError ->
Logger.error("Device #{device_id} not found")
{:error, :device_not_found}
error ->
Logger.error("Monitoring check failed for device #{device_id}: #{inspect(error)}")
{:error, error}
end
defp ping_device(device) do
# Use configured ping adapter (mockable in tests)
ping_adapter().ping(device.ip_address, 1000)
end
end