Dynamic function dispatch with Elixir
I am creating a small application that acts as a broker that connects to N different services.
Any client that connects to this broker can send data to any service. This is done by sending some JSON data which contains the payload along with the name of the service that should receive it.
My code has one module per service. Each one of those modules knows how to do its thing.
Initially, I had a case where I chose what module I should call based on what the user had sent. Something along these lines:
This works fine for a handful of services. But when I added a new one I had to remember to edit this file.
Also, I added ecto. And it validating that the service name was valid was also something that I should be doing.
So, I needed a way to:
- have a list of the valid service names
- dynamically find the module for a given service name
Turns out this is something that you can already introspect with one simple erlang call to
:code.all_loaded. This is in part what
IEx does with its autocompletion.
So, after calling
:code.all_loaded what’s left is to find all the module names that match what I am looking for.
In my case, all the Services implement a specific callback and all are named
This will return all modules which start with
Then it’s just a matter of finding which module ‘listens’ or ‘accepts’ a specific service name. For that, I each module has to have a function called
accepted_names which returns a list of service names it can process. This is enforced by a behaviour.
Here’s the relevant code.
Now, in my ecto schema I can have the following validation:
Also, I can make a function call just by knowing the service name:
I don’t claim this is THE way to do this. It works for me.
If anyone knows a better way to do this or a better name for it, please hit me up on twitter.