alexandrubagu
Handle_info when using Task.Supervisor.async_nolink
Hi,
I want to handle the following exit example ( String.to_integer(input) is jus an example and can be replaced with raise). This happen when I call My.GenServer.some_method(My.GenServer, "test"). I will be grateful if someone has a suggestion for this.
10:26:42.321 [error] GenServer My.GenServer terminating
** (stop) exited in: Task.await(%Task{owner: #PID<0.124.0>, pid: #PID<0.128.0>, ref: #Reference<0.4181578440.4035444737.94083>}, 5000)
** (EXIT) an exception was raised:
** (ArgumentError) argument error
:erlang.binary_to_integer("test")
Here’s the code:
defmodule My.Application do
use Application
def start(_type, _args) do
import Supervisor.Spec, warn: false
children = [
worker(My.GenServer, []),
supervisor(Task.Supervisor, [[name: My.Task.Supervisor, restart: :transient]]),
]
opts = [strategy: :one_for_one, name: Test.Supervisor]
Supervisor.start_link(children, opts)
end
end
defmodule My.GenServer do
def start_link do
GenServer.start_link(__MODULE__, :ok, name: __MODULE__)
end
def init(:ok) do
# Process.flag(:trap_exit, true)
{:ok, []}
end
def some_method(pid, input) do
GenServer.call(pid, {:some_method, input})
end
def handle_call({:some_method, input}, _from, state) do
# because we don't want to terminate GenServer use Task.async_nolink
task = Task.Supervisor.async_nolink(My.Task.Supervisor, fn ->
# raise argument error when passing binary
String.to_integer(input)
end)
{:reply, Task.await(task), state}
end
def handle_info({:EXIT, from, reason}, state) do
IO.inspect "handle_info::exit"
IO.inspect reason
{:noreply, state}
end
def handle_info({_ref, result}, state) do
IO.inspect "handle_info::result"
IO.inspect result
{:noreply, state}
end
def handle_info({:DOWN, _ref, :process, _pid, reason}, state) do
IO.inspect "handle_info::down"
IO.inspect reason
{:noreply, state}
end
def handle_info(msg, state) do
IO.inspect "handle_info"
IO.inspect msg
{:noreply, state}
end
end
I’ve read the docs from here regarding Task.Supervisor.async_link: if you create a task using async_nolink inside an OTP behaviour like GenServer, you should match on the message coming from the task inside your GenServer.handle_info/2 callback.
My problem is that handle_info is not called, I try to debug using observer attaching a trace to My.GenServer and I see that My.GenServer is receiving a :DOWN message:
Any solution to this problem ?
Thanks
Most Liked
NobbZ
When using Task.await/1 it will handle the :DOWN-message from the Task. It will handle it by calling exit/1. So the GenServer will be exited because of that.
If you want to be more failsafe, you have to do the waiting for the result and the :DOWN-message completely on your own.
dom
Oh, I see what you mean. Instead of using await you can store the task’s ref and the caller in your GenServer state, then use GenServer.reply in your handle_info to send back the response to the caller.
NobbZ
As it is now you gain nothing from the Task except for the timeout, you could do the work in the GenServer directly and it wouldn’t matter (as long as no timout would happen in the Task)
The more correct way were to put the returned task into your state, alongside the from and return a :noreturn tuple in handle_call/3.
Some time later you will receive a message with either the result of the computation done in the Task, which you then can GenServer(from, answer) to your caller.
Or you might receive a :DOWN, which you will need to find ways to tell your caller about. Most idiomatic way were to use an :error-tuple I think.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #javascript
- #code-sync
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance










