Add Dialyzer typespecs to WebSocket agent code and Agents context
- Add @spec to AgentSocket callbacks (connect/3, id/1) - Add @spec to AgentChannel callbacks (join/3, handle_info/2, handle_in/3) - Add @spec to AgentChannel private function build_jobs_for_agent/1 - Add @spec to Agents.verify_agent_token/1 - Add @spec to Agents.update_agent_token_heartbeat/3 - Add @spec to Agents.list_agent_polling_targets/1 These specs provide strict type checking for the critical WebSocket agent communication code implemented in this session.
This commit is contained in:
parent
bdde71462a
commit
e1b9976219
3 changed files with 11 additions and 1 deletions
|
|
@ -102,6 +102,8 @@ defmodule Towerops.Agents do
|
|||
{1, nil}
|
||||
|
||||
"""
|
||||
@spec update_agent_token_heartbeat(Ecto.UUID.t(), String.t() | nil, map() | nil) ::
|
||||
{non_neg_integer(), nil | [term()]}
|
||||
def update_agent_token_heartbeat(agent_token_id, ip_address, metadata \\ nil) do
|
||||
now = DateTime.truncate(DateTime.utc_now(), :second)
|
||||
|
||||
|
|
@ -133,6 +135,7 @@ defmodule Towerops.Agents do
|
|||
{:error, :invalid_token}
|
||||
|
||||
"""
|
||||
@spec verify_agent_token(String.t()) :: {:ok, AgentToken.t()} | {:error, :invalid_token}
|
||||
def verify_agent_token(token) do
|
||||
with {:ok, token_string} <- AgentToken.verify_token(token),
|
||||
%AgentToken{} = agent_token <-
|
||||
|
|
@ -238,6 +241,7 @@ defmodule Towerops.Agents do
|
|||
[%Equipment{snmp_enabled: true, site: %Site{}, snmp_device: %Device{sensors: [...], interfaces: [...]}}]
|
||||
|
||||
"""
|
||||
@spec list_agent_polling_targets(Ecto.UUID.t()) :: [Equipment.t()]
|
||||
def list_agent_polling_targets(agent_token_id) do
|
||||
# Use SQL to filter equipment by effective agent assignment
|
||||
# This avoids loading all equipment into memory and filtering in application code
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ defmodule ToweropsWeb.AgentChannel do
|
|||
require Logger
|
||||
|
||||
@impl true
|
||||
@spec join(String.t(), map(), Phoenix.Socket.t()) ::
|
||||
{:ok, Phoenix.Socket.t()} | {:error, map()}
|
||||
def join("agent:" <> _agent_id, %{"token" => token}, socket) do
|
||||
# Verify agent token from join payload
|
||||
case Agents.verify_agent_token(token) do
|
||||
|
|
@ -60,6 +62,7 @@ defmodule ToweropsWeb.AgentChannel do
|
|||
end
|
||||
|
||||
@impl true
|
||||
@spec handle_info(:send_jobs, Phoenix.Socket.t()) :: {:noreply, Phoenix.Socket.t()}
|
||||
def handle_info(:send_jobs, socket) do
|
||||
jobs = build_jobs_for_agent(socket.assigns.agent_token_id)
|
||||
job_list = %AgentJobList{jobs: jobs}
|
||||
|
|
@ -70,6 +73,7 @@ defmodule ToweropsWeb.AgentChannel do
|
|||
end
|
||||
|
||||
@impl true
|
||||
@spec handle_in(String.t(), map(), Phoenix.Socket.t()) :: {:noreply, Phoenix.Socket.t()}
|
||||
def handle_in("result", %{"binary" => binary_b64}, socket) do
|
||||
binary = Base.decode64!(binary_b64)
|
||||
result = SnmpResult.decode(binary)
|
||||
|
|
@ -77,7 +81,6 @@ defmodule ToweropsWeb.AgentChannel do
|
|||
{:noreply, socket}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_in("heartbeat", %{"binary" => binary_b64}, socket) do
|
||||
binary = Base.decode64!(binary_b64)
|
||||
heartbeat = AgentHeartbeat.decode(binary)
|
||||
|
|
@ -108,6 +111,7 @@ defmodule ToweropsWeb.AgentChannel do
|
|||
|
||||
# Private helpers
|
||||
|
||||
@spec build_jobs_for_agent(Ecto.UUID.t()) :: [AgentJob.t()]
|
||||
defp build_jobs_for_agent(agent_token_id) do
|
||||
agent_token_id
|
||||
|> Agents.list_agent_polling_targets()
|
||||
|
|
|
|||
|
|
@ -13,12 +13,14 @@ defmodule ToweropsWeb.AgentSocket do
|
|||
channel "agent:*", ToweropsWeb.AgentChannel
|
||||
|
||||
@impl true
|
||||
@spec connect(map(), Phoenix.Socket.t(), map()) :: {:ok, Phoenix.Socket.t()}
|
||||
def connect(_params, socket, _connect_info) do
|
||||
# Allow all connections - authentication happens at channel join
|
||||
{:ok, socket}
|
||||
end
|
||||
|
||||
@impl true
|
||||
@spec id(Phoenix.Socket.t()) :: String.t() | nil
|
||||
def id(socket) do
|
||||
# Return nil before authentication (channel join will set agent_token_id)
|
||||
case Map.get(socket.assigns, :agent_token_id) do
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue