Splits cohesive sub-domains out of lib/towerops/snmp.ex into dedicated submodules under lib/towerops/snmp/. Public API preserved via defdelegate in Towerops.Snmp. - Towerops.Snmp.Vlans, IpAddresses, Processors, StorageQueries - Towerops.Snmp.Mempools, Sensors, Interfaces, Neighbors Neighbors uses Towerops.Devices.DeviceQuery.for_organization/1 to remove inline org_id filters. snmp.ex shrinks from 2742 to 2159 lines.
116 lines
3.1 KiB
Elixir
116 lines
3.1 KiB
Elixir
defmodule Towerops.Snmp.Mempools do
|
|
@moduledoc """
|
|
Read-side queries and mutations for memory pools discovered on SNMP devices,
|
|
plus persistence for mempool time-series readings.
|
|
|
|
Extracted from `Towerops.Snmp` to keep the context module focused.
|
|
"""
|
|
|
|
import Ecto.Query
|
|
|
|
alias Towerops.Repo
|
|
alias Towerops.Snmp.Mempool
|
|
alias Towerops.Snmp.MempoolReading
|
|
|
|
@doc """
|
|
Lists all memory pools for a device.
|
|
"""
|
|
def list_mempools(snmp_device_id) do
|
|
Mempool
|
|
|> where([m], m.snmp_device_id == ^snmp_device_id)
|
|
|> order_by([m], m.mempool_index)
|
|
|> Repo.all()
|
|
end
|
|
|
|
@doc """
|
|
Updates a mempool with the given attributes.
|
|
"""
|
|
def update_mempool(mempool, attrs) do
|
|
mempool
|
|
|> Mempool.changeset(attrs)
|
|
|> Repo.update()
|
|
end
|
|
|
|
@doc """
|
|
Gets recent mempool readings for a memory pool.
|
|
|
|
## Options
|
|
|
|
- `:limit` - Maximum number of readings to return (default: 100)
|
|
- `:since` - Only return readings after this datetime
|
|
"""
|
|
def get_mempool_readings(mempool_id, opts \\ []) do
|
|
limit = Keyword.get(opts, :limit, 100)
|
|
since = Keyword.get(opts, :since)
|
|
|
|
MempoolReading
|
|
|> where([r], r.mempool_id == ^mempool_id)
|
|
|> order_by([r], desc: r.checked_at)
|
|
|> limit(^limit)
|
|
|> maybe_filter_since(since)
|
|
|> Repo.all()
|
|
end
|
|
|
|
defp maybe_filter_since(query, nil), do: query
|
|
defp maybe_filter_since(query, since), do: where(query, [r], r.checked_at >= ^since)
|
|
|
|
@doc """
|
|
Gets the latest mempool reading for a memory pool.
|
|
"""
|
|
def get_latest_mempool_reading(mempool_id) do
|
|
MempoolReading
|
|
|> where([r], r.mempool_id == ^mempool_id)
|
|
|> order_by([r], desc: r.checked_at)
|
|
|> limit(1)
|
|
|> Repo.one()
|
|
end
|
|
|
|
@doc """
|
|
Gets the latest mempool readings for multiple memory pools in a single query.
|
|
|
|
Returns a map of %{mempool_id => reading} for efficient batch loading.
|
|
Mempools without readings will not be present in the map.
|
|
"""
|
|
def get_latest_mempool_readings_batch([]), do: %{}
|
|
|
|
def get_latest_mempool_readings_batch(mempool_ids) when is_list(mempool_ids) do
|
|
from(r in MempoolReading,
|
|
where: r.mempool_id in ^mempool_ids,
|
|
distinct: r.mempool_id,
|
|
order_by: [asc: r.mempool_id, desc: r.checked_at]
|
|
)
|
|
|> Repo.all()
|
|
|> Map.new(fn reading -> {reading.mempool_id, reading} end)
|
|
end
|
|
|
|
@doc """
|
|
Records a new mempool reading.
|
|
"""
|
|
def create_mempool_reading(attrs) do
|
|
%MempoolReading{}
|
|
|> MempoolReading.changeset(attrs)
|
|
|> Repo.insert()
|
|
end
|
|
|
|
@doc """
|
|
Batch inserts multiple mempool readings using `Repo.insert_all/3`.
|
|
|
|
Accepts a list of attribute maps with the same keys as `create_mempool_reading/1`.
|
|
Generates UUIDs and timestamps automatically. Returns `{count, nil}`.
|
|
"""
|
|
@spec create_mempool_readings_batch([map()]) :: {non_neg_integer(), nil}
|
|
def create_mempool_readings_batch([]), do: {0, nil}
|
|
|
|
def create_mempool_readings_batch(entries) when is_list(entries) do
|
|
now = Towerops.Time.now()
|
|
|
|
rows =
|
|
Enum.map(entries, fn entry ->
|
|
entry
|
|
|> Map.put(:id, Ecto.UUID.generate())
|
|
|> Map.put(:inserted_at, now)
|
|
end)
|
|
|
|
Repo.insert_all(MempoolReading, rows)
|
|
end
|
|
end
|