trisolaran

trisolaran

How are DB connections passed from the test process to the liveview process when using the ecto sandbox?

Hello!

I noticed that if I have a LV test that uses the Ecto sandbox in manual mode, the LV process in the test has “magically” access to the sandboxed DB connection created by the test process. This is really amazing but I don’t understand how it works :slight_smile:

Simplified example:

Liveview:

defmodule MyAppWeb.LiveView do
  @moduledoc false

  import Ecto.Query

  use MyAppWeb, :live_view

  @impl true
  def mount(_params, _session, socket) do
    connect_params = get_connect_params(socket)

    IO.inspect(connect_params, label: "connect_params")
    IO.inspect(self(), label: "I'm the LV")
    Repo.all(MyApp.User) |> length() |> IO.inspect(label: "users")

    {:ok, socket}
  end
end

Test setup:

defmodule MyAppWeb.ConnCase do
  ...

  setup tags do
    Ecto.Adapters.SQL.Sandbox.mode(MyApp.Repo, :manual)

    :ok = Ecto.Adapters.SQL.Sandbox.checkout(MyApp.Repo)

    {:ok, conn: Phoenix.ConnTest.build_conn()}
  end
end

The actual test:

defmodule MyAppWeb.LiveViewTest do 
    use MyAppWeb.ConnCase

    test "just to prove a point", %{conn: conn} do 
      insert_test_records_in_user_table(20)

      IO.inspect(self(), label: "I'm the test process")

      {:ok, view, html} = live(conn, "/live_view")
   end 
end

Output:

1 I'm the test process: #PID<0.869.0>
2 connect_params: nil
3 I'm the LV: #PID<0.869.0>
4 entries: 20
5 connect_params: %{"_mounts" => 0}
6 I'm the LV: #PID<0.873.0>
7 entries: 20

Lines 2-4 come from the static LV mount, and lines 5-7 from the connected one. As you can see, the static mount happens in the same process as the test’s, while the connected mount happens in a different process. So far nothing strange. What I don’t understand is how the connected LV can see the test records inserted by the test process, even though I didn’t change the mode of the sandbox to shared or call Ecto.Adapters.SQL.Sandbox.allow. I would have expected the DB access from the connected LV process to fail with the error:
** (DBConnection.OwnershipError) cannot find ownership process for #PID<0.873.0>

The only explanation I can think of is that the sandboxed DB connection is somehow passed over to the LV process when this latter is spawned, by calling Ecto.Adapters.SQL.Sandbox.allow somewhere. But I couldn’t find where this happens in the code.

Can someone please clarify this for me?

Marked As Solved

Also Liked

LostKobrakai

LostKobrakai

There we‘re some blogposts around the introduction to the functionality for Tasks, which is by now a lot of elixir versions back. While ecto sandbox piggibacks on this, it‘s afaik meant to be a much more general feature (hence it‘s inclusion in elixir core). But it should probably still be mentioned in the docs that processes supporting $caller keys might get automatic concurrent support with the sandbox.

LostKobrakai

LostKobrakai

The sandbox uses the mechanic described here to track the caller (aka the test process) for a LV: Task — Elixir v1.12.3

With that pid as key it can fetch the connection checked out by that process.

Where Next?

Popular in Questions Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New
JulienCorb
I am trying to implement my new.html.eex file to create new posts on my website. new.html.eex: &lt;h1&gt;Create Post&lt;/h1&gt; &lt;%= ...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
jaysoifer
Is there a way to rollback a specific migration and only that one (“skipping” all the other ones)? Would mix ecto.rollback -v 200809061...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New

Other popular topics Top

danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 29603 241
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

We're in Beta

About us Mission Statement