From 54b08bfb18f764b6cc149d8e8a832f112ae00507 Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Thu, 15 Jan 2026 07:28:14 -0600 Subject: [PATCH] Add database indexes and optimize SNMP polling - Added partial indexes for alerts and SNMP equipment queries - Fixed missing agent_assignments association in Equipment schema - Fixed missing preloads to avoid N+1 queries - Optimized Rust agent SNMP credential field access --- lib/towerops/agents.ex | 2 +- lib/towerops/equipment/equipment.ex | 1 + ...115011502_add_alerts_equipment_indexes.exs | 28 +++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 priv/repo/migrations/20260115011502_add_alerts_equipment_indexes.exs diff --git a/lib/towerops/agents.ex b/lib/towerops/agents.ex index 861d6fc7..300e22b7 100644 --- a/lib/towerops/agents.ex +++ b/lib/towerops/agents.ex @@ -244,7 +244,7 @@ defmodule Towerops.Agents do from(e in Equipment, where: e.snmp_enabled == true, preload: [ - :site, + :agent_assignments, site: :organization, snmp_device: [:sensors, :interfaces] ] diff --git a/lib/towerops/equipment/equipment.ex b/lib/towerops/equipment/equipment.ex index cbdd2047..85bd9ff0 100644 --- a/lib/towerops/equipment/equipment.ex +++ b/lib/towerops/equipment/equipment.ex @@ -27,6 +27,7 @@ defmodule Towerops.Equipment.Equipment do belongs_to :site, Towerops.Sites.Site has_one :snmp_device, Towerops.Snmp.Device + has_many :agent_assignments, Towerops.Agents.AgentAssignment timestamps(type: :utc_datetime) end diff --git a/priv/repo/migrations/20260115011502_add_alerts_equipment_indexes.exs b/priv/repo/migrations/20260115011502_add_alerts_equipment_indexes.exs new file mode 100644 index 00000000..12290da3 --- /dev/null +++ b/priv/repo/migrations/20260115011502_add_alerts_equipment_indexes.exs @@ -0,0 +1,28 @@ +defmodule Towerops.Repo.Migrations.AddAlertsEquipmentIndexes do + use Ecto.Migration + + def change do + # Composite index for active alerts queries - filters by type and resolved status + # Used by list_organization_active_alerts/1 and get_active_alert/2 + # Partial index only on unresolved alerts for efficiency + create_if_not_exists index(:alerts, [:equipment_id, :alert_type, :resolved_at], + where: "resolved_at IS NULL", + name: :idx_alerts_equipment_type_unresolved + ) + + # Composite index for SNMP-enabled equipment polling queries + # Used by list_snmp_enabled_equipment/0 and agent polling target queries + # Partial index only on SNMP-enabled equipment + create_if_not_exists index(:equipment, [:snmp_enabled, :last_snmp_poll_at], + where: "snmp_enabled = true", + name: :idx_equipment_snmp_poll + ) + + # Composite index for monitoring-enabled equipment with SNMP + # Covers common query pattern: WHERE snmp_enabled AND monitoring_enabled + create_if_not_exists index(:equipment, [:snmp_enabled, :monitoring_enabled, :site_id], + where: "snmp_enabled = true AND monitoring_enabled = true", + name: :idx_equipment_snmp_monitoring_site + ) + end +end