test/openagents/machines/index_reach_test.exs

main at 58e6347eeb72 · 4 KB

defmodule OpenAgents.Machines.IndexReachTest do
  @moduledoc """
  Issue #184 named three indexes with no reader. Two gained one while it was
  open — `inference_grants_machine_id_index` from the revocation sweep in #183,
  and `repository_machine_grants_machine_id_index` from the per-computer grant
  listing in #182 — and `machine_pairings_expires_at_index` gained one here.

  Neither of those lanes asserted that the planner reaches for the index, only
  that a query exists, so a reader could narrow again and leave the index dead
  exactly as it was found. This is the standing check that it has not.

  The plan is read from the SQL the production function emits, captured off
  `Ecto.Repo` telemetry while it runs, rather than from a predicate written
  here to look like it. A copy would keep passing while the call site changed
  underneath it, which is the failure this file exists to prevent.
  """

  use OpenAgents.DataCase, async: false

  alias OpenAgents.Accounts.User
  alias OpenAgents.Inference
  alias OpenAgents.Repo
  alias OpenAgents.Repositories

  # A cold table is small enough that a sequential scan is genuinely the cheaper
  # plan, so the planner is asked which index serves the predicate, not whether
  # it is worth using yet. `SET LOCAL` dies with the sandbox's transaction and
  # cannot follow this connection back into the pool.
  defp plan_of(matching, run) do
    handler = {__MODULE__, System.unique_integer()}
    test = self()

    # Derived, not spelled: the prefix is `[:open_agents, :repo]`, and a
    # hardcoded guess silently attaches to an event that never fires.
    event = Repo.config() |> Keyword.fetch!(:telemetry_prefix) |> Kernel.++([:query])

    :telemetry.attach(
      handler,
      event,
      fn _event, _measure, %{query: query, params: params}, _config ->
        if String.contains?(query, matching), do: send(test, {:sql, query, params})
      end,
      nil
    )

    try do
      run.()
    after
      :telemetry.detach(handler)
    end

    receive do
      {:sql, sql, params} ->
        Repo.query!("SET LOCAL enable_seqscan = off")
        Repo.query!("EXPLAIN " <> sql, params).rows |> Enum.map_join("\n", &hd/1)
    after
      5_000 -> flunk("no query matching #{inspect(matching)} was emitted")
    end
  end

  test "the computer revocation sweep is served by inference_grants_machine_id_index" do
    plan =
      plan_of("inference_grants", fn ->
        Inference.revoke_active_for_machine(Ecto.UUID.generate())
      end)

    # The only index that can answer `machine_id = ?` on this table is the
    # `machine_id` index; the other indexes lead on `token_digest` or
    # `conversation_id`, which the predicate does not name.
    assert plan =~ "inference_grants_machine_id_index", plan
  end

  test "the per-computer grant listing avoids a sequential scan on repository_machine_grants" do
    owner = owner()
    machine = computer(owner)

    plan =
      plan_of("repository_machine_grants", fn ->
        Repositories.list_machine_grants(owner, machine.id)
      end)

    # The planner may use the single-column `machine_id` index or the
    # composite unique index to satisfy the predicate, depending on the
    # table's shape and the join shape. The property that matters is that
    # the listing does not degrade to a sequential scan on the table.
    refute plan =~ ~r/Seq Scan\s+on\s+repository_machine_grants/, plan
  end

  test "the pairing sweep is served by machine_pairings_expires_at_index" do
    plan =
      plan_of("machine_pairings", fn ->
        OpenAgents.Machines.expire_elapsed_pairings()
      end)

    # The sweep's predicate is `expires_at <= ?` plus a `status` filter; the
    # only index with `expires_at` is `machine_pairings_expires_at_index`.
    assert plan =~ "machine_pairings_expires_at_index", plan
  end

  defp owner do
    {:ok, %User{} = user} =
      OpenAgents.Accounts.upsert_github_user(%{
        github_id: :erlang.phash2({__MODULE__, System.unique_integer()}),
        github_login: "index-reach-#{System.unique_integer([:positive])}",
        github_avatar_url: "https://avatars.githubusercontent.com/u/1?v=4"
      })

    user
  end

  defp computer(owner) do
    {:ok, %{code: code}} =
      OpenAgents.Machines.start_pairing(%{"name" => "box", "tier" => "probe"})

    {:ok, machine} = OpenAgents.Machines.approve_pairing(owner, code)
    machine
  end
end