From b3d8436290c9adee52ba86f652358852e09324f5 Mon Sep 17 00:00:00 2001 From: Ayla Croft Date: Sat, 26 Sep 2026 15:30:21 -0400 Subject: [PATCH] Observed tests: wait for the restarted collector's init before reading it (G-090) The floor leg failed once in "a call during the restart gap is answered...": snapshot/1 answered {:error, :not_started} after the loop had found the restarted pid. GenServer registers the name before init/1 runs, and init/1 creates the table snapshot/1 reads, so a poll on the name can land between the two; the floor runner is slow enough to. Both restart tests now make a call to the new process (:sys.get_state/1, answered only after init returns) before reading it. Measured: with a 200 ms sleep put into init/1 before the table, the old tests fail (both of them: the kill test had the same window, latent) and the new ones pass; unmodified, 30 seeds, 0 failures. No package change: the gap is the collector's documented restart gap, and it ends when init returns. Signed-off-by: Ayla Croft --- test/beam_mcp/connectome/observed_test.exs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/beam_mcp/connectome/observed_test.exs b/test/beam_mcp/connectome/observed_test.exs index e5fc179..3893723 100644 --- a/test/beam_mcp/connectome/observed_test.exs +++ b/test/beam_mcp/connectome/observed_test.exs @@ -162,6 +162,10 @@ defmodule BeamMCP.Connectome.ObservedTest do assert Process.alive?(sup) assert is_pid(new) + # The name is registered before init/1 runs, and init/1 creates the table snapshot/1 + # reads: the gap lasts until init returns. A call to the process is answered only after + # it has (the floor leg read between the two once, G-090's record). + _ = :sys.get_state(new) assert {:ok, %Graph{nodes: [], edges: []}} = Observed.snapshot(name) ids = Enum.map(:telemetry.list_handlers([:beam_mcp, :dispatch, :stop]), & &1.id) @@ -215,6 +219,10 @@ defmodule BeamMCP.Connectome.ObservedTest do end) assert is_pid(new) + # The name is registered before init/1 runs, and init/1 creates the table snapshot/1 + # reads: the gap lasts until init returns. A call to the process is answered only after + # it has (the floor leg read between the two once, G-090's record). + _ = :sys.get_state(new) assert {:ok, %Graph{edges: []}} = Observed.snapshot(name) call(state, :echo) assert {:ok, %Graph{edges: [%Edge{weight: 1}]}} = Observed.snapshot(name)