Reputation: 1339
I'm spawning a function with Task.async/3
and get the result with Task.yield/2
with a timeout. When the function completes, the calling process receives two messages:
{#Reference<0.2781211517.3250323457.144521>, the_result_of_the_function}
where the#Reference
is the reference of the monitor returned by Task.async/3
, and
{:DOWN, #Reference<0.2781211517.3250323457.144521>, :process, #PID<0.24500.0>, :normal}
which is sent by the monitor to inform that the monitored process (the task) has shutdown.
If the task finishes before the timeout, Task.yield/2
takes these messages out of the mailbox and returns the proper result. However, if the task finishes after the timeout, Task.yield/2
returns nil
and the program flow is already somewhere else when these two messages arrive.
I implemented two handle_info
handlers to get these messages out of the mailbox. Yet, it's probably a bad idea because as I have no way to get only messages from expired tasks, (I don't see any way to "register" the #Reference
of the task that has timeout-ed), I will probably remove valid massages before they are read by Task.yield/2
.
What am I missing and how to get around this problem ?
Upvotes: 0
Views: 321
Reputation: 54684
The documentation for Task.yield/2
suggests the following approach:
If the time runs out before a message from the task is received, this function will return
nil
and the monitor will remain active. […] If you intend to shut the task down if it has not responded within timeout milliseconds, you should chain this together withshutdown/1
, like so:case Task.yield(task, timeout) || Task.shutdown(task) do {:ok, result} -> result nil -> Logger.warn "Failed to get a result in #{timeout}ms" nil end
Upvotes: 1