defmodule SomeMonitor do
use GenServer
@timeout 5_000
def start_link(_) do
GenServer.start_link(__MODULE__, [], name: __MODULE__)
end
@impl true
def init(state) do
Process.flag(:trap_exit, true)
Process.send(self(), :kickoff_update, state)
{:ok, state}
end
@impl true
def handle_info(
:kickoff_update,
state
) do
DoStuff.launch()
Process.send(self(), :update_transactions, state)
{:noreply, state}
end
@impl true
def handle_info(:update_transactions, state) do
timeout_reference = Process.send_after(self(), :job_timeout, @timeout)
task =
Task.Supervisor.async(
TasksSupervisor,
fn -> PyOperatorSupervisor.launch({[], "get_fresh_info", "main"}) end
)
results = Task.await(task, 10_000)
Process.cancel_timer(timeout_reference)
case results do
{:ok, _} ->
{:ok, _} = ReviewTransactions.main(results)
Process.send(self(), :update_transactions, state)
{:noreply, state}
{:error, reason} ->
{:stop, reason, state}
end
{:noreply, state}
end
@impl true
def handle_info(:job_timeout, state) do
LogBook.main(
"Still waiting for job to finish . . . Elapsed time: #{@timeout / 1000} second(s).",
__MODULE__,
70,
:warning
)
{:noreply, state}
end
@impl true
def handle_info({:EXIT, _, :normal}, state), do: {:noreply, state}
@impl true
def handle_info(critical_error, state), do: {:stop, critical_error, state}
@impl true
def terminate(critical_error, state),
do: LogBook.main({state, critical_error}, __MODULE__, 77, :error)
end
What’s an efficient approach to avoid Process.send_after/3
from being blocked by Task.await/2
?