src/erqwest_runtime.erl

%% @private
%%
%% This gen_server monitors the tokio runtime so that its failure can be handled
%% by the supervision tree (for example in the case of a panic). Since this is
%% not expected to happen, the reference to the runtime is stored in a
%% persistent_term for efficiency.

-module(erqwest_runtime).

-behaviour(gen_server).

-export([start_link/0, get/0]).

%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
         terminate/2]).

-record(state, {runtime}).

-define(SERVER, ?MODULE).

start_link() ->
  gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).

get() ->
  persistent_term:get(?MODULE).

%% gen_server implementation

init([]) ->
  process_flag(trap_exit, true),
  Runtime = erqwest_nif:start_runtime(self()),
  persistent_term:put(?MODULE, Runtime),
  {ok, #state{runtime=Runtime}}.

handle_call(_Request, _From, State) ->
  {reply, ok, State}.

handle_cast(_Request, State) ->
  {noreply, State}.

handle_info(erqwest_runtime_stopped, State) ->
  {stop, erqwest_runtime_failure, State#state{runtime=undefined}};
handle_info(_Info, State) ->
  {noreply, State}.

terminate(_Reason, #state{runtime=undefined}) ->
  ok;
terminate(_Reason, #state{runtime=Runtime}) ->
  erqwest_nif:stop_runtime(Runtime),
  receive
    erqwest_runtime_stopped -> ok
  end.