I have a gen_server module, I use gun as http client to make a long pull connection with a http server, so I call gun:open in my module's init, but if gun:open fail, my module fail, so my application fail to start. What is the proper way to do this. The following is my code:
init() ->
lager:debug("http_api_client: connecting to admin server...~n"),
{ok, ConnPid} = gun:open("localhost", 5001),
{ok, Protocol} = gun:await_up(ConnPid),
{ok, #state{conn_pid = ConnPid, streams = #{},protocol = Protocol}}.
Basically you have two options: either your process requires the HTTP server to be available (your current solution), or it doesn't, and handles requests while the connection to the HTTP server is down gracefully (by returning error responses). This blog post presents this idea more eloquently: https://ferd.ca/it-s-about-the-guarantees.html
You could do that by separating this code out into a separate function, that doesn't crash if the connection fails:
And call this function from
init
. That is, regardless of whether you can connect, your gen_server will start.Then, when you make a request to this gen_server that requires the connection to be present, check whether it is
undefined
:Of course, that means that if the connection fails at startup, your gen_server will never try to connect again. You could add a timer, or you could add an explicit
reconnect
command:The code above doesn't handle the case when the connection goes down while the gen_server is running. You could handle that explicitly, or you could just let your gen_server process crash in that case, so that it restarts into the "not connected" state.