Hi, I’m trying to see if there’s a way to find all the modules that implement a behaviour, but from an escript.
This is one way I tried extracting those:
defp modules_implementing_behaviour(behaviour) do
for {module, _} <- :code.all_loaded(),
behaviour in (module.module_info(:attributes)
|> Keyword.get_values(:behaviour)
|> List.flatten()) do
module
end
end
Another attempt was this (also required adding :mix
to :external_applications
in mix.exs
):
# copied from https://github.com/findmypast/behaviour-introspection
defp modules_implementing_behaviour(behaviour) do
# Ensure the current projects code path is loaded
Mix.Task.run("loadpaths", [])
# Fetch all .beam files
Path.wildcard(Path.join([Mix.Project.build_path(), "**/ebin/**/*.beam"]))
# Parse the BEAM for behaviour implementations
|> Stream.map(fn path ->
{:ok, {mod, chunks}} = :beam_lib.chunks('#{path}', [:attributes])
{mod, get_in(chunks, [:attributes, :behaviour])}
end)
# Filter out behaviours we don't care about and duplicates
|> Stream.filter(fn {_mod, all_behaviours} ->
is_list(all_behaviours) && behaviour in all_behaviours
end)
|> Stream.map(fn {module, _} -> module end)
|> Enum.uniq()
end
None of those actually work like that. The first one did kind of work if I did Code.ensure_loaded?(AModuleThatImplementsTargetBehaviour)
, but it defeats the purpose since I’d need to manually list all the related modules.
The problem I’m trying to solve is a project that knows how to perform a data sync between two databases. It has a number of sync scenarios to choose from. The whole idea is to create an escript
that accepts a param that determines which data sync scenario we want, starts the application, finds that scenario and executes it. Not even sure that the escript
is the correct way to do it. Thought of releases but can’t find a nice way to wrap it all up as an executable. Docker is something that would work but I was hoping to find a way without that. I can even make it a service that exposes some API and can be triggered via http, but that seems like an overkill for something so simple.
Anyway, thank you for your time