Using a macro to load and report config data?

On occasion, I need to load some configuration data for later access. At present, I’m using an Actor for this, but that seems like overkill.

Assuming that I won’t need to reload the data at runtime, it seems like I could define a macro that loads the data at compile time and generates code that simply returns a data structure. However, I can’t figure out how to do this. Comments? Suggestions? (ducks)

@Rich_Morin It always helps if you can show us what you’ve tried so far.

As a general approach though I’m not sure I recommend this approach. It makes it harder to deploy to different environments that may need different configuration (staging vs production). You have to create unique compilation artifacts for each instead of a single compilation artifact that you pass configuration into.

@Rich_Morin It always helps if you can show us what you’ve tried so far.

I tried and discarded a couple of approaches. For example:

defmacro foo(file_path) do
  data = File.read(file_path)
  quote do
    unquote(data)
  end
end

As a general approach though I’m not sure I recommend this approach. …

Point taken. Still, I’d like to know how to do it.

Maybe persistent_term?

Something like this? :slight_smile:

defmodule MyConfig do
  @config File.read!("config.txt") |> String.split("\n") |> # ... etc
  def config, do: @config
end

I do this rather a lot and don’t see any problem with it. The key is to determine if it’s environment specific configuration (i.e. database creds) or some fixed part of your domain (i.e. a mapping between ids and statuses used in your industry).

2 Likes

I do not think this is overkill, and depending on your exact situation it is probably the right solution, because:

  • Configuration is read/parsed from the file system or other external sources only once, rather than each time it is requested
  • Configuration can be requested many times.
  • The Configuration is made when the Actor starts up (which probably will be during application startup, assuming that you’ve made part of your supervision tree). Configuration problems will therefore make your app startup fail fast, which is probably good.
  • And finally it is still possible to refresh your configuration by restarting the actor after changes have been made.

For many tasks, the actor that keeps the configuration is the same one that performs the work based on this configuration (or delegates this to other processes), which makes this even less of an ‘overkill’-situation.


The only times it would be useful to work with configuration during compilation time are:

  1. You try to do something that can only be done during compilation (e.g. Elixir log levels, including optional AST in consumer modules, etc).
  2. Extreme efficiency is required, so we want to compile the results of the configuration.

As @benwilson512 already noted, these are a lot less flexible in how/when they can be configured.