How to detect if a module implemented genserver callbacks

Hi all

How can I detect if a module is implement GenServer callbacks?

Thanks

1 Like

You can use module_name.module_info[:attributes][:behaviour] for this.

4 Likes

I want to write a supervisor that will on the start_link function expect as the argument a module and number of workers. Consider following supervisor:

defmodule ProcessDiscovery.WorkerSuperVisor do

  use Supervisor

  def start_link(module, numbers) do
    Supervisor.start_link(__MODULE__, {module, numbers})
  end

  def init({module, numbers}) do

    workers = for w <- 1..numbers  do
			worker(module, [], id: {:worker, w})
    end

    # supervise/2 is imported from Supervisor.Spec
    supervise(workers, strategy: :one_for_one)
  end

end

As you can see, I will create workers depends on number that the user will pass. What I want to do is, to ensure that the user pass a module with implemented genserver. Otherwise it should throw error.

How can I validate a parameter, that should be a module? It is a good idea to use @spec in this scenario?

Thanks

As @Nobbz said, you can use module.module_info[:attributes][:behaviour] to see what behaviours the module implements.

You could then write your check as:

unless Enum.member?(module.module_info[:attributes][:behaviour], GenServer) do
  raise "Module #{inspect(module)} must implement GenServer to be used as a worker" 
end

Just some thoughts. You’re requiring that the worker use the GenServer behaviour but that would exclude any workers written in erlang or workers that implement the interface fully and don’t implement the behaviour. Are you sure you need a hard check here? Might it not be better just to document your expectations?

I’ve never think about it. That a good argumentation I would let it like you sad.

Thanks