diff --git a/lib/towerops/agents.ex b/lib/towerops/agents.ex index 300e22b7..2ec88b02 100644 --- a/lib/towerops/agents.ex +++ b/lib/towerops/agents.ex @@ -239,55 +239,27 @@ defmodule Towerops.Agents do """ def list_agent_polling_targets(agent_token_id) do - # Get all equipment with necessary preloads - equipment_query = + # Use SQL to filter equipment by effective agent assignment + # This avoids loading all equipment into memory and filtering in application code + Repo.all( from(e in Equipment, - where: e.snmp_enabled == true, + join: s in assoc(e, :site), + join: o in assoc(s, :organization), + left_join: aa in AgentAssignment, + on: aa.equipment_id == e.id and aa.enabled == true, + where: + e.snmp_enabled == true and + (aa.agent_token_id == ^agent_token_id or + (is_nil(aa.agent_token_id) and s.agent_token_id == ^agent_token_id) or + (is_nil(aa.agent_token_id) and is_nil(s.agent_token_id) and + o.default_agent_token_id == ^agent_token_id)), preload: [ :agent_assignments, site: :organization, snmp_device: [:sensors, :interfaces] ] ) - - equipment_list = Repo.all(equipment_query) - - # Filter to only equipment that resolves to this agent - Enum.filter(equipment_list, fn equipment -> - equipment_matches_agent?(equipment, agent_token_id) - end) - end - - defp equipment_matches_agent?(equipment, agent_token_id) do - # Check direct assignment first - case get_equipment_assignment(equipment.id) do - %AgentAssignment{agent_token_id: ^agent_token_id, enabled: true} -> - true - - %AgentAssignment{} -> - # Has a different direct assignment - false - - nil -> - # No direct assignment, check site then org - site = equipment.site - site_matches_agent?(site, agent_token_id) - end - end - - defp site_matches_agent?(site, agent_token_id) do - cond do - # Check site agent - site.agent_token_id == agent_token_id -> - true - - # Check org default (only if site doesn't have an agent set) - is_nil(site.agent_token_id) and site.organization.default_agent_token_id == agent_token_id -> - true - - true -> - false - end + ) end @doc """