Current section
Files
Jump to
Current section
Files
lib/codex/task_support.ex
defmodule Codex.TaskSupport do
@moduledoc false
@default_supervisor Codex.TaskSupervisor
@type task_start_error ::
:noproc | {:task_start_failed, term()} | {:application_start_failed, term()}
@spec async_nolink((-> any())) :: {:ok, Task.t()} | {:error, task_start_error()}
def async_nolink(fun) when is_function(fun, 0) do
async_nolink(@default_supervisor, fun)
end
@spec async_nolink(pid() | atom(), (-> any())) :: {:ok, Task.t()} | {:error, task_start_error()}
def async_nolink(supervisor, fun) when is_function(fun, 0) do
with :ok <- ensure_started_for(supervisor) do
maybe_retry_noproc(supervisor, fn -> do_async_nolink(supervisor, fun) end)
end
end
defp maybe_retry_noproc(@default_supervisor = supervisor, starter) do
case starter.() do
{:error, :noproc} ->
with :ok <- ensure_started_for(supervisor) do
starter.()
end
result ->
result
end
end
defp maybe_retry_noproc(_supervisor, starter), do: starter.()
defp ensure_started_for(@default_supervisor) do
case Application.ensure_all_started(:codex_sdk) do
{:ok, _started_apps} -> :ok
{:error, reason} -> {:error, {:application_start_failed, reason}}
end
end
defp ensure_started_for(_supervisor), do: :ok
defp do_async_nolink(supervisor, fun) do
{:ok, Task.Supervisor.async_nolink(supervisor, fun)}
catch
:exit, {:noproc, _} ->
{:error, :noproc}
:exit, :noproc ->
{:error, :noproc}
:exit, reason ->
{:error, {:task_start_failed, reason}}
end
end