I have a system that creates a Question
and inserts this question into the database, I do this by clicking a link that I've set up. This is straightforward Phoenix stuff. Create a controller action setup a link for it and then click the button to fire that action.
This works for now. But the next phase is to have the system create a question without any intervention from the UI. So, that leads me to a new place with Elixir/Phoenix. My new problem is: I need to run this function automatically at x time of day.
What is the most idiomatic way of implementing a background task in Elixir/Phoenix? I know very little about Genserver or Supervisors but I think I'm ready to start learning about these tools. With all that being said, how would you approach a the problem of moving logic to a background job.
def build_question(conn, _params) do
case Questions.create_total_points_question(conn) do
{:ok, _question} ->
conn
|> put_flash(:info, "Question created successfully.")
|> redirect(to: page_path(conn, :index))
{:error, _msg} ->
conn
|> redirect(to: page_path(conn, :index))
end
end
This controller action is triggered from a link. This code needs to be called in the background. Thanks for the help in advance.
You have few options.
One is to simple run Task.async
in your action, but that links process which executes your action with the one you spawned, so task crash will affect process which spawned it and awaits it. BTW, in your particular case I don't think you want this in your action since you don't have anything to work with while awaiting for the result, so it is unnecessary.
Second option, in case you don't want to await for the result is to use Task.start_link
. This is ok, but again as name of start function is, the tasks process is linked to yours, so crashes in any of those two will cause other to crash too.
Third option, is to use Task.Supervisor
, just open your app ex file (probably one which has name as you project and it is in lib folder) and under children = [...
list add at the bottom like this
children = [
...
supervisor(Task.Supervisor,[], [name: MyApp.TaskSupervisor])
]
this will start supervisor process in your app with name MyApp.TaskSupervisor
which than you can call and tell what code to run and supervise it.
Now this third option gives you a bit more control in your app since:
You can find more info about this in documentation