problem asynchronizing ecto calls

I’ve realized that I misdiagnosed your problem.

When I tried to reproduce the error you’re getting, I realized that I had been thinking of the other error that occurs when a process cannot find a checked out connection. It looks like this:

11:14:40.287 [error] Task #PID<0.244.0> started from #PID<0.241.0> terminating                                                                                              
** (DBConnection.OwnershipError) cannot find ownership process for #PID<0.244.0>.                                                                                           
                                                                                                                                                                            
When using ownership, you must manage connections in one                                                                                                                    
of the four ways:                                                                                                                                                           

[...it goes on for a while...]

However, the error you’re getting must be caused by the test process exiting before another process stopped using the DB connection. I was only able to reproduce this as follows:

  test "Task.Supervisor.async_stream" do
    enum = [1, 2, 3]

    stream =
      Task.Supervisor.async_stream_nolink(
        Module.TaskSupervisor,
        enum,
        fn item -> my_func(item, 2) end,
        ordered: false,
        max_concurrency: 1
      )

    _result = Enum.to_list(stream)

    # We have to sleep here to allow the process spawned by my_func() 
    # to enter a transaction
    on_exit(fn ->
      Process.sleep(100)
    end)
  end

  defp my_func(user_id, _n) do
    Project.Repo.get(Project.User, user_id)

    # I could only get the error to occur when I spawned another process here.
    spawn(fn ->
      # This transaction starts before the test process exits but it sleeps for a while
      # to let the test process terminate. Then, when Project.Repo.get() is called, it'll
      # raise the error
      # Postgrex.Protocol (#PID<0.210.0>) disconnected: ** (DBConnection.ConnectionError) owner #PID<0.241.0> exited
      Project.Repo.transaction(fn ->
        Process.sleep(100)
        Project.Repo.get(Project.User, user_id)
      end)
    end)
  end

The full error I’m getting looks a bit different from yours, but I think it happen in a similar circumstance:

11:19:10.365 [error] Postgrex.Protocol (#PID<0.210.0>) disconnected: ** (DBConnection.ConnectionError) owner #PID<0.241.0> exited                                           
                                                                                                                                                                            
Client #PID<0.247.0> is still using a connection from owner at location:                                                                                                    
                                                                                                                                                                            
    (elixir) lib/process.ex:228: Process.sleep/1                                                                                                                            
    test/sandbox_test.exs:29: anonymous fn/1 in SandboxTest.my_func/2                                                                                                       
    (ecto_sql) lib/ecto/adapters/sql.ex:814: anonymous fn/3 in Ecto.Adapters.SQL.checkout_or_transaction/4                                                                  
    (db_connection) lib/db_connection.ex:1349: DBConnection.run_transaction/4                                                                                               
                                                                                                                                                                            
The connection itself was checked out by #PID<0.247.0> at location: 

In the end, you were right about your tests running with async: false since that the default, so my analysis was wrong in that regard. However, I think there’s something else going on in your test suite outside of the code snippets you’ve shared so far.