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.
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).
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:
You try to do something that can only be done during compilation (e.g. Elixir log levels, including optional AST in consumer modules, etc).
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.