Delay the startup of an application while waiting for a dependency to be started

I have an application with an external dependency (let’s call it Dep). When my application (App) starts up, the first thing it does it that it also tries to make a connection to Dep.
But when I deploy or do integration tests, I start Dep and App at roughly the same time. Dep takes a while to start (5-20seconds).

My current workaround is to introduce sleep in the startup scripts, but this is quite error prone, so I would like to solve it in a clean way.

My initial tought was to try to make a connection, when that fails, sleep for 2 seconds and try again. If it succeeds, start up. But is that allowed in Application.start/2? Or can I delay the startup in the GenServer.init?

What would be the correct way to solve this? Thanks!

Here is a good post on the topic: https://ferd.ca/it-s-about-the-guarantees.html

If you need your connections when the app boots, then you need to start and wait for them. But if you don’t, then in your init callback you can send a message to yourself and pick it up immediately.

def init(...) do
  send(self(), :async_init)
  {:ok, ...state...}
end

def handle_info(:async_init, state) do
  # finish init
  {:noreply, state}
end
5 Likes

Thanks, that’s a great post!