fix live polling to use effective agent from site/org cascade

live poll mode used get_device_assignment which only checks direct
device-level assignments. devices with agent assigned at site or
org level fell through to direct Phoenix SNMP. replaced with
get_effective_agent_token which walks the full cascade.
This commit is contained in:
Graham McIntire 2026-02-11 14:12:42 -06:00
parent 6d597f7e76
commit 45357e334a
No known key found for this signature in database
2 changed files with 40 additions and 37 deletions

View file

@ -1,6 +1,15 @@
CHANGELOG - towerops-web
========================
2026-02-11 - fix: live polling uses effective agent from site/org cascade
- File: lib/towerops_web/live/graph_live/show.ex
- Bug: Live poll mode used Agents.get_device_assignment/1 which only checks
direct device-level assignments. Devices with agent assigned at site or
org level fell through to direct Phoenix SNMP instead of routing to agent.
- Fix: Replaced with Agents.get_effective_agent_token/1 which walks the
device → site → org cascade, matching how regular polling resolves agents.
Also simplified request_agent_live_poll_and_wait to accept token_id directly.
2026-02-11 - fix: round sensor values to 1 decimal place
- Files: lib/towerops/workers/device_poller_worker.ex (poll_simple_sensor/2),
lib/towerops_web/channels/agent_channel.ex (process_sensor_reading/3)

View file

@ -686,16 +686,16 @@ defmodule ToweropsWeb.GraphLive.Show do
now = DateTime.utc_now()
timestamp_ms = DateTime.to_unix(now, :millisecond)
# Check if device has agent assignment (fresh check each poll to avoid stale data)
has_agent = Agents.get_device_assignment(device.id) != nil
# Check effective agent (device → site → org cascade)
agent_token_id = Agents.get_effective_agent_token(device)
Logger.info("Live poll for device #{device.name}: has_agent=#{has_agent}")
Logger.info("Live poll for device #{device.name}: agent_token_id=#{inspect(agent_token_id)}")
new_points =
if has_agent do
if agent_token_id do
# Request agent to poll NOW and wait for result
Logger.info("Requesting live poll from agent")
request_agent_live_poll_and_wait(device.id, socket.assigns)
request_agent_live_poll_and_wait(device.id, agent_token_id, socket.assigns)
else
# Do direct SNMP polling for specific sensors only
Logger.info("Using direct SNMP for live polling")
@ -724,39 +724,33 @@ defmodule ToweropsWeb.GraphLive.Show do
end
# Request live poll from agent and wait for response
defp request_agent_live_poll_and_wait(device_id, assigns) do
case Agents.get_device_assignment(device_id) do
nil ->
defp request_agent_live_poll_and_wait(device_id, agent_token_id, assigns) do
# Generate unique reply topic for this request
reply_topic = "live_poll_reply:#{:erlang.unique_integer([:positive])}"
# Subscribe to reply topic
:ok = Phoenix.PubSub.subscribe(Towerops.PubSub, reply_topic)
# Get sensors we're interested in
sensors = get_sensors_for_live_mode(assigns)
sensor_oids = Enum.map(sensors, & &1.sensor_oid)
# Broadcast live poll request with reply topic and sensor OIDs
Phoenix.PubSub.broadcast(
Towerops.PubSub,
"agent:#{agent_token_id}:live_poll",
{:live_poll_requested, device_id, sensor_oids, reply_topic}
)
# Wait for response with timeout
receive do
{:live_poll_result, oid_values} ->
# Process the OID values into data points
process_live_poll_oids(sensors, oid_values)
after
3000 ->
Logger.warning("Live poll timeout waiting for agent response")
[]
assignment ->
# Generate unique reply topic for this request
reply_topic = "live_poll_reply:#{:erlang.unique_integer([:positive])}"
# Subscribe to reply topic
:ok = Phoenix.PubSub.subscribe(Towerops.PubSub, reply_topic)
# Get sensors we're interested in
sensors = get_sensors_for_live_mode(assigns)
sensor_oids = Enum.map(sensors, & &1.sensor_oid)
# Broadcast live poll request with reply topic and sensor OIDs
Phoenix.PubSub.broadcast(
Towerops.PubSub,
"agent:#{assignment.agent_token_id}:live_poll",
{:live_poll_requested, device_id, sensor_oids, reply_topic}
)
# Wait for response with timeout
receive do
{:live_poll_result, oid_values} ->
# Process the OID values into data points
process_live_poll_oids(sensors, oid_values)
after
3000 ->
Logger.warning("Live poll timeout waiting for agent response")
[]
end
end
end