Start tasks when supervisor starts

I currently have a couple Task's that are responsible for sending some emails. In the event of a server restart, I’d like to be able to pull all the records from my database that still need emails to be sent and then start some Task's to finish the job.

What is the best way to spawn Task's when the supervisor restarts? Does it make sense to use something other than Task and Task.Supervisor?

Sure, you can do this. Simply pass a Task as one of your workers like this:

  defmodule MySupervisor do
    use Supervisor

    def init([]) do
      tasks = [fn -> do_something() end]

      children = [
        worker(Task, tasks, restart: :transient),
      ]

      supervise(children, strategy: :one_for_one)
    end
  end

This will start the tasks and, by using :transient option, they will be performed just once after the supervisor starts its children. I hope this answers your question :slight_smile:

3 Likes

I’ve been playing around with this a little bit and it’s starting to make sense. If I want my tasks to be supervised would I need multiple supervisors? One for finishing unfinished tasks I pull from the database and another for supervising new tasks?

1 Like

You may give your Supervisor a name and add children to the supervision tree directly from your worker.

defmodule Worker do
  ...
  import Supervisor.Spec
  
  defp something do
    [] # list of emails to be sent(?)
    |> Enum.map(
      fn data ->
        Supervisor.start_child(
          MySupervisor,
          worker(Task, data) # Supervisor.Spec.worker
        )
      end
    )
  end
  ...
end
1 Like

Is this possible with a :one_for_one supervisor? I tried playing around with something like this yesterday but was only able to get it working for :simple_one_for_one.

1 Like

@satom99 I think I got this working.

Thanks, @mkaszubowski and @satom99 for your help!

1 Like