mbaeuerle

mbaeuerle

Ecto test multiple process transaction in sandbox with shared connection

I basically have a similar setup like the one described in the sandbox docs for a shared mode connection, which looks like this:

setup do
  :ok = Ecto.Adapters.SQL.Sandbox.checkout(Repo)
  Ecto.Adapters.SQL.Sandbox.mode(Repo, {:shared, self()})
end

test "create two posts, one sync, another async" do
  task = Task.async(fn ->
    Repo.insert!(%Post{title: "async"})
  end)
  assert %Post{} = Repo.insert!(%Post{title: "sync"})
  assert %Post{} = Task.await(task)
end

Which runs fine.
Now when I change this example slightly and wrap both inserts in a transaction:

test "create two posts, one sync, another async" do
  Repo.transaction(fn ->
    task = Task.async(fn ->
      Repo.insert!(%Post{title: "async"})
    end)
    assert %Post{} = Repo.insert!(%Post{title: "sync"})
    assert %Post{} = Task.await(task)
  end)
end

This leads to a timeout:

 ** (EXIT from #PID<0.478.0>) exited in: GenServer.call(#PID<0.479.0>, {:checkout, #Reference<0.0.3.2012>, true, 15000}, 5000)
     ** (EXIT) time out

.10:04:12.191 [error] Postgrex.Protocol (#PID<0.383.0>) disconnected: ** (DBConnection.ConnectionError) owner #PID<0.478.0> exited while client #PID<0.478.0> is still running with: exited in: GenServer.call(#PID<0.479.0>, {:checkout, #Reference<0.0.3.2012>, true, 15000}, 5000)
** (EXIT) time out

I am wondering if this is because I can’t use transactions with the shared mode or if I am missing something else. I am using PostgreSQL 9.6.2, Ecto 2.1.4 and Elixir 1.4.2

Marked As Solved

michalmuskala

michalmuskala

The answer is that Ecto transactions, in general, can’t span multiple processes.

Also Liked

hubertlepicki

hubertlepicki

You probably want to test the spawned functions separately in that case. But you can create nested transactions form the same process, this should not be the issue at all. As long as you stay within the same process you should have no issues.

For the cases you have to spawn processes that do database operations, I would go with combination of async: false in your test cases, and switching to shared mode: https://hexdocs.pm/ecto/2.2.8/Ecto.Adapters.SQL.Sandbox.html#module-shared-mode

The end result should be that these tests will not run in parallel with other tests, so possibly would be slower than doing it in parallel, but there is nothing stopping you from havihng some tests running in parallel, and others not.

al2o3cr

al2o3cr

You can definitely do both things with Ecto.Adapters.SQL.Sandbox, but depending on exactly how the process is spawned you may need to manually ensure the connection gets shared using Ecto.Adapters.SQL.Sandbox.allow.

IIRC, on Elixir 1.8+ the original poster’s use of a Task spawned from the test process will automatically share the DB connection.

Where Next?

Popular in Questions Top

_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New
polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
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
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
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New
hpopp
To simplify some tasks at work, I wrote and published this package yesterday. It’s a simple macro that enables Access behaviour on struct...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New

Other popular topics Top

sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: https://hexdocs.pm/ecto/Ecto.Schema.html#module-...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 35421 110
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
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
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New

We're in Beta

About us Mission Statement