Problem
LiveView processes that subscribe to PubSub topics receive messages in handle_info. When the message handler queries the DB (e.g. Ash.get!), it fails with "record not found" because the LiveView process doesn't have the test's Ecto sandbox access.
The LiveView process IS in the test's $callers chain (sandbox propagated during mount via the sandbox plug). But when a PubSub message arrives from a different process (e.g. Oban worker, another test's LiveView), the handle_info runs in the LiveView's process context — which still has sandbox access from mount.
The issue is that the DB record was created in the test's sandbox transaction, but by the time handle_info fires, the LiveView might be trying to access it through a different connection or the sandbox transaction may have been rolled back.
Reproduction
# test setup creates district in sandbox
district = Test.Factories.District.create(%{name: "Test"})
# LiveView mounts, subscribes to "sync:created" PubSub topic
{:ok, view, _html} = live(conn, "/portal/sync/districts")
# Test triggers a sync which broadcasts PubSub message
# LiveView handle_info receives it and calls:
# Ash.get!(Rosters.District, resource_id)
# This fails: "record not found" because the district
# was created in the test's sandbox transaction
Workaround
async: false — shared sandbox mode gives all processes access to the same data.
Environment
- sandbox_case 0.3.7
- Phoenix LiveView 1.1.27
- Ecto SQL 3.13.5
Problem
LiveView processes that subscribe to PubSub topics receive messages in
handle_info. When the message handler queries the DB (e.g.Ash.get!), it fails with "record not found" because the LiveView process doesn't have the test's Ecto sandbox access.The LiveView process IS in the test's
$callerschain (sandbox propagated during mount via the sandbox plug). But when a PubSub message arrives from a different process (e.g. Oban worker, another test's LiveView), thehandle_inforuns in the LiveView's process context — which still has sandbox access from mount.The issue is that the DB record was created in the test's sandbox transaction, but by the time
handle_infofires, the LiveView might be trying to access it through a different connection or the sandbox transaction may have been rolled back.Reproduction
Workaround
async: false— shared sandbox mode gives all processes access to the same data.Environment