zac
Testing in Ash & "(DBConnection.OwnershipError) cannot find ownership process for #PID"
I just spent half a day trying to figure out how to get around this:
(DBConnection.OwnershipError) cannot find ownership process for #PIDxxx
Most of the time was spent trying to find decent references. I didn’t find anything in the Ash docs itself, and the examples I did find made no mention of connection contention (in fact, the examples are very straightforward using ETS, so contention probably isn’t an issue…)
I’m thinking an edit to the Ash Testing topic would be nice…? Perhaps adding mention of how this can seemingly bite you out of nowhere (my simple app was fine, then “something happened,” it tipped over the edge I guess, and suddenly all my tests stopped working).
I’d be happy to do a PR. Haven’t done one before, imagine the docs in github somewhere…
All that said, before making said PR, wanted to double-check what I’ve learned, as this was new territory for me:
(DBConnection.OwnershipError) cannot find ownership process for pid … root cause
Ecto docs and a few posts quickly point toward shared connection contention, particularly when using async tests.
What confused me: Various posts / Ecto docs made it sound like turning off async: true would fix the issue. Not so that did nothing.
Other info led me to believe switching from a :manual to either :auto (nope) or :shared (doesn’t exist anymore) sandbox mode would help. (Neither did).
While both strategies are offered in the Ecto docs, neither did anything toward fixing the problem. ¯_(ツ)_/¯
Ecto docs are confusing
Just that. The Ecto.Adapters.SQL.Sandbox docs offer a few different strategies. The way I interpreted the docs, I should be adding this to my tests:
setup do
# Explicitly get a connection before each test
:ok = Ecto.Adapters.SQL.Sandbox.checkout(WasteWalk.Repo)
# Setting the shared mode must be done only after checkout
Ecto.Adapters.SQL.Sandbox.mode(WasteWalk.Repo, {:shared, self()})
end
That did fix the tests but left me with another problem. All kinds of Postgrex.Protocol (pid<0.404.0>) disconnected: ** (DBConnection.ConnectionError) cropping up (not just in my tests but a lot of framework tests). Made the situation worse.
What I settled on…
I ended up with just this in my tests:
setup do
:ok = Ecto.Adapters.SQL.Sandbox.checkout(WasteWalk.Repo)
end
This is a new project – major upgrade from my last one (which used older Elixir, Phoenix, Ash). Didn’t have to worry about any of this “in the old days,” so… something new.
So far so good. Tests are working, nothing else has broken. I still don’t completely understand why it’s necessary (well, in theory, I suppose I do… more accurately, I don’t understand why turning on async:true didn’t solve the problem, nor why using a shared connection resulted in so much horrible fallout).
Anyhow, any further advice or explanation is welcome. Like I said, if there’s consensus this would be a good add for the docs I’ll do a PR. Hopefully with a better explanation than, “well, this fixed it, dunno why tho.” ![]()
Marked As Solved
zachdaniel
Okay, found an issue where the installer would sometimes not set those when installing into an existing app.
Typically, you see something like use MyApp.DataCase, not use ExUnit.Case
For tunez that looks like this, which has sandbox setup.
defmodule Tunez.DataCase do
@moduledoc """
This module defines the setup for tests requiring
access to the application's data layer.
You may define functions here to be used as helpers in
your tests.
Finally, if the test case interacts with the database,
we enable the SQL sandbox, so changes done to the database
are reverted at the end of every test. If you are using
PostgreSQL, you can even run database tests asynchronously
by setting `use Tunez.DataCase, async: true`, although
this option is not recommended for other databases.
"""
use ExUnit.CaseTemplate
using do
quote do
alias Tunez.Repo
import Ecto
import Ecto.Changeset
import Ecto.Query
import Ash.Test
import Tunez.DataCase
import Tunez.Generator
import Tunez.Support.Helpers
end
end
setup tags do
Tunez.DataCase.setup_sandbox(tags)
:ok
end
@doc """
Sets up the sandbox based on the test tags.
"""
def setup_sandbox(tags) do
pid = Ecto.Adapters.SQL.Sandbox.start_owner!(Tunez.Repo, shared: not tags[:async])
on_exit(fn -> Ecto.Adapters.SQL.Sandbox.stop_owner(pid) end)
end
@doc """
A helper that transforms changeset errors into a map of messages.
assert {:error, changeset} = Accounts.create_user(%{password: "short"})
assert "password is too short" in errors_on(changeset).password
assert %{password: ["password is too short"]} = errors_on(changeset)
"""
def errors_on(changeset) do
Ecto.Changeset.traverse_errors(changeset, fn {message, opts} ->
Regex.replace(~r"%{(\w+)}", message, fn _, key ->
opts |> Keyword.get(String.to_existing_atom(key), key) |> to_string()
end)
end)
end
end
Also Liked
LostKobrakai
In ExUnit tests each run in their own process (setup first, then the test itself, see ExUnit.Callbacks — ExUnit v1.20.2 ). The ecto sandbox is coupled to the lifecycle of a single test. `setup_all` runs separately before individual tests are excuted and is therefore outside the isolation of the per test sandboxing.
Last Post!
LostKobrakai
In ExUnit tests each run in their own process (setup first, then the test itself, see ExUnit.Callbacks — ExUnit v1.20.2 ). The ecto sandbox is coupled to the lifecycle of a single test. `setup_all` runs separately before individual tests are excuted and is therefore outside the isolation of the per test sandboxing.
Popular in Questions
Other popular topics
Latest Ash Threads
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #hex
- #security









