GenServer pass file path

My guidelines for config is as follows:

  1. If it’s functions, receive config via params
  2. If it’s processes, receive config via params given to the childspec
  3. If the above is not convenient for the default use case, additionally fall back to application env or other stateful configuration methods.

For your case I’m wondering why you need a process (genserver) at all. If all you do is either startup or not you don’t really need to check the genserver at runtime anymore. If things failed the app doesn’t start to begin with.

I’d go for:

with {:ok, result} <- Lib.populate(path) do
  case result do
    :indexation_successful -> Logger.info("Application launched successfully.")
    {:partial_indexation_successful, fails} -> Logger.info("Application launched with errors. Check the CSV file for: #{inspect fails}")
  end
  Logger.info("Waiting for requests.")
  Supervisor.start_link(children, opts)
end

You could add more logging to the failing part, but the not starting application does already cause logs to be generated. If you’d skip the logging for the success case it’s even more simple than that.

An alternative I can see, which doesn’t require wrapping Supervisor.start_link could be:

children = [
  {Lib.Populator, [path]},
  …
]
Supervisor.start_link(children, opts)

Where the Populator succeeds or fails to start depending on the result of loading the file. After a success the process could just hibernate. Here the population would be done at init/1 and block till finished and everything starting later can just use the data as needed.

If you don’t want to block on startup you can use the above as well, do the loading after init/1, but you essentially need to query the state of loading the file whenever you try to access it and also it’s not as straight forward in terms of stopping the application, as there might already be more things started.