Skip to content

Commit f6e9eba

Browse files
authored
Fix flaky ShapeCache test (#2859)
Before this change, it was easy to see the test fail after just a handful of runs. The reason was that the simulated snapshotter process would be resumed before the test process had started waiting on the snapshot. This change makes sure there's a process in the consumer's waiting list before resuming the simulated snapshotter, though it does make the test aware of implementation details. This test has failed in two CI jobs spawned by the [commit in `main`](fbbcad4) that was supposed to publish a new version of Electric and other packages.
1 parent fbbcad4 commit f6e9eba

1 file changed

Lines changed: 24 additions & 6 deletions

File tree

packages/sync-service/test/electric/shape_cache_test.exs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -792,13 +792,10 @@ defmodule Electric.ShapeCacheTest do
792792

793793
{shape_handle, _} = ShapeCache.get_or_create_shape_handle(@shape, opts)
794794

795-
task =
796-
Task.async(fn ->
797-
send(test_pid, {:await_snapshot_start, self()})
798-
ShapeCache.await_snapshot_start(shape_handle, opts)
799-
end)
795+
task = Task.async(ShapeCache, :await_snapshot_start, [shape_handle, opts])
800796

801-
assert_receive {:await_snapshot_start, _pid}
797+
consumer_pid = GenServer.whereis(Electric.Shapes.Consumer.name(ctx.stack_id, shape_handle))
798+
await_for_consumer_to_have_waiters(consumer_pid)
802799

803800
assert_receive {:waiting_point, ref, pid}
804801
send(pid, {:continue, ref})
@@ -1236,4 +1233,25 @@ defmodule Electric.ShapeCacheTest do
12361233
|> Enum.map(&Jason.decode!/1)
12371234
|> Enum.sort_by(fn %{"value" => value} -> value[sort_col] end)
12381235
end
1236+
1237+
defp await_for_consumer_to_have_waiters(consumer, num_attempts \\ 3)
1238+
1239+
defp await_for_consumer_to_have_waiters(_consumer, 0) do
1240+
raise "No process started waiting on shape in time"
1241+
end
1242+
1243+
defp await_for_consumer_to_have_waiters(consumer, num_attempts) do
1244+
# We're looking up the process state directly here to be sure that the consumer has waiters
1245+
# on the snapshot before proceeding with the snapshot failure simulation. This adds
1246+
# coupling to the implementation of the consumer module but, on the other hand, it does
1247+
# prevent flake we used to see here.
1248+
case :sys.get_state(consumer).awaiting_snapshot_start do
1249+
[] ->
1250+
Process.sleep(50)
1251+
await_for_consumer_to_have_waiters(consumer, num_attempts - 1)
1252+
1253+
other ->
1254+
other
1255+
end
1256+
end
12391257
end

0 commit comments

Comments
 (0)