Simplify all_loaded call
Today it is defined as:
defp all_loaded do
timed_log "all loaded", 1 do
Applications.get_modules_from_applications()
|> Enum.filter(fn module ->
try do
Code.ensure_loaded?(module) and function_exported?(module, :module_info, 0)
rescue
_ ->
false
end
end)
end
end
Unfortunately, Code.ensure_loaded? is a bit expensive. Luckily, Application.spec(:app_name, :modules) should return correct and up to date information, except for the current app and path dependencies, since "live code compilation" (as done by Phoenix and others) may define new modules and without reload the application spec (which would require the app to stop).
So my suggestion is to improve Applications.get_modules_from_applications() to Application.spec(:app_name, :modules) for all apps, except the current apps and path deps (which you can compute on boot). For those, you do a File.ls(path_to_ebin) and get the beam files. This should actually fix bugs, given if you define a module in a Phoenix app today, it likely won't be picked by Applications.get_modules_from_applications()?
@josevalim Applications.get_modules_from_applications() calls :application.get_key(app, :modules) which is exactly the same as Application.spec(:app_name, :modules). The code in question loads the modules to find ones implementing a plugin behaviour.
Yes, I understand that. My comment was not about the get_key/spec part, but about ensure_loaded. This is a very expensive operation and, if it is only needed for plug-ins, then it should likely be called once on boot, but I would strongly suggest to make plugins opt-in on the mix.exs file. :)
The plugins are mix deps from the client project. Loading them at boot is not possible. One option is doing that after initial mix compile.