lib/openagents/capacity/broker.ex

58e6347eeb72 · 1 KB

defmodule OpenAgents.Capacity.Broker do
  @moduledoc false

  @behaviour OpenAgents.Capacity.Evidence

  @allowed_keys [
    "id",
    "logical",
    "active_reservations",
    "reported_free",
    "queued",
    "observed_limit",
    "budget_limit",
    "drain_limit",
    "observed_at",
    "estimated_wait_seconds",
    "private",
    "incident_drained"
  ]

  @impl true
  def fetch(_viewer) do
    config = Application.get_env(:openagents, OpenAgents.Capacity, [])
    url = Keyword.get(config, :broker_url)

    if is_binary(url) and String.trim(url) != "" do
      request_options = [
        url: String.trim_trailing(url, "/") <> "/capacity",
        method: :get,
        receive_timeout: Keyword.get(config, :broker_timeout_ms, 2_000),
        retry: false
      ]

      request_options =
        case Keyword.get(config, :broker_token) do
          token when is_binary(token) and token != "" ->
            Keyword.put(request_options, :headers, [{"authorization", "Bearer " <> token}])

          _missing ->
            request_options
        end

      case Req.request(request_options) do
        {:ok, %Req.Response{status: status, body: body}} when status in 200..299 ->
          parse(body)

        {:ok, %Req.Response{}} ->
          {:error, :broker_unavailable}

        {:error, _reason} ->
          {:error, :broker_unavailable}
      end
    else
      {:error, :unconfigured}
    end
  end

  defp parse(%{"classes" => classes}) when is_list(classes) do
    {:ok, %{"classes" => Enum.flat_map(classes, &parse_class/1)}}
  end

  defp parse(_invalid), do: {:error, :invalid_broker_response}

  defp parse_class(class) when is_map(class) do
    id = Map.get(class, "id")

    if is_binary(id) do
      [Map.take(class, @allowed_keys)]
    else
      []
    end
  end

  defp parse_class(_invalid), do: []
end