What's the correct way to handle async tasks I don't care about in an ExUnit test? "[error] Postgrex.Protocol disconnected"

If I have a piece of code that calls Task.start/1(e.g. sending an email async, or creating a row in the DB), and in that task I access the DB, then when I run my tests (even if I don’t care about the results of that task), I get the following error:

[error] Postgrex.Protocol (#PID<0.546.0>) disconnected: ** (DBConnection.ConnectionError) owner #PID<0.870.0> exited

Client #PID<0.561.0> is still using a connection from owner at location:

I know it’s because the task is trying to access the DB connection after the test process has finished, but is there a proper way of handling this? Or just ignore the errors?

Some options are:

  1. Start the task under a supervisor (which is always a good practice) and register an on_exit callback at the end of each test that waits until all supervised tasks finish. Very similar to what is recommended for phoenix presence.

2, Don’t start the tasks at all (have an option or config to control it)

  1. Run those functions inline instead of in a task (have an option or config to control it)

I usually go for 1.

2 Likes

Great idea. Thanks, Jose. So instead of Task.start/1 I would create a Task.Supervisor process, and start the async task with Task.Supervisor.start_child(MyTaskSup, &some_fun/0), and then in my test I would write:

on_exit(fn ->
  for pid <- Task.Supervisor.children(MyTaskSup) do
    ref = Process.monitor(pid)
    assert_receive {:DOWN, ^ref, _, _, _}, 1000
  end
end)

Is there something similar to this for GenStage? Can I check when my consumer is finished with it’s events?

For GenStage you would have to send it a message or a special event that lets you know it is done.