Database queries not executed inside Task.Supervisor

I have the following in my application.ex:

  def start(_type, _args) do
    children = [
      ...
      {Task.Supervisor, name: Amplify.UpdateMetaAudiencesSupervisor}
    ]
    opts = [strategy: :one_for_one, name: Amplify.Supervisor]
    Supervisor.start_link(children, opts)
  end

Then in my controller method I have:

    Task.Supervisor.async(Amplify.UpdateMetaAudiencesSupervisor, fn ->
      IO.inspect("Inside async") # this prints fine
      Amplify.Context.Audiences.get_audiences() # this makes a DB call
     IO.inspect("After DB call") # never gets printed and no SQL logs 
      end)
    end)

I don’t see any SQL statements being printed for the DB call and even if I put raise "error" inside the get_audiences(), I see no error messages in the logs.

How can I perform DB operations inside a Task.Supervisor (and have them printed to logs)?

Nothing immediately jumps to mind, could you share parts of the Amplify.Context.Audiences.get_audiences() function source?

Thank you for responding.

Here it is:

  def get_audiences() do
      IO.inspect("this will print")
      Audience
      |> preload([:ad_platform_account, :venues, :participants, :products])
      |> Repo.all()
      |> IO.inspect() # this will not print
  end

Is the Repo started when You start your supervisor?

The supervisor is listed after the Repo, so yes?

    children = [
      AmplifyWeb.Telemetry,
      Amplify.Repo,
      {OpenIDConnect.Worker, Application.get_env(:amplify, :openid_connect_providers)},
      {DNSCluster, query: Application.get_env(:amplify, :dns_cluster_query) || :ignore},
      {Phoenix.PubSub, name: Amplify.PubSub},
      Lapin.Supervisor,
      {Finch, name: Amplify.Finch},
      {Task.Supervisor, name: Amplify.UpdateMetaAudiencesSupervisor},
      AmplifyWeb.Endpoint
    ]

The router.ex has this:

  scope "/public", AmplifyWeb do
    get "/audiences/update", MetaController, :update_meta_audiences
  end

I got this to work with Task.Supervisor.async_nolink() instead of Task.Supervisor.async() but I’m not fully understanding why that is working for me.

My guess: Task.Supervisor.async still links the Task to the calling process - in the case of the controller, that’s the request handler process. When the request finishes, that process exits and the Task is terminated.

2 Likes

Thank you. That makes sense to me.

You are better off having a dedicated supervisor just for these tasks. As @al2o3cr pointed out, you were linking them to the process of the request and that ends quickly very often.

1 Like