Partly compile-time, partly dynamic config section

I have a config section which is composed of 2 parts: a static one which I keep in config.exs and a dynamic one which I add into runtime.exs. The dynamic part may get changed frequently, hence runtime.exs

I don’t consider using runtime.exs completely for everything

In such cases, what’s the proper way to read this config section:

Application.compile_env(...) or Application.get_env(...) ?

Read the compile time parts with Application.compile_env(...) (and a full path to those keys) and the runtime ones with Application.get_env(...).

But I want to the whole section.

Application.compile_env(..) will raise an exception. Therefore, Application.get_env gets left and will work. But won’t it create some bugs in some specific circumstances?

Elixir raises an expection when you try to change config used at compile time at runtime. This is meant to prevent people from shooting themselfes in the foot, because those runtime changes to config understandably won’t be able to apply back to the compiled code. So either you’re currently falling for that right now or you’re not using your whole “section” at compile time, but still select the whole thing with Application.compile_env.

1 Like

One of the two, or none. It’s not answered my question

Application.get_env returns runtime config merged over compile time config, i.e. it’s the conglomeration of the two.

Or are you saying you want to see runtime config only?

No, I want to access the whole section at once. A section includes compile-time and runtime values, though.

# compile-time config
config, :my_app, :my_section,
  static1: 1,
  static2: "fdsafds",
#  dyn1: 999,  # this  may get changed often
  static3: [
    a1: 1,
    a2: "fdsfds443999",
  ]

# runtime.exs
# read dyn1 from ENV
# dyn_value = ....
# ....
# then

config, :my_app, :my_section,
 dyn1: dyn_value

And yes, I’m currently using Application.get_env(...) for it.

defmodule MyApp.M1 do
   @my_cfg_section Application.get_env(:my_app, :my_section)
   # ...........

What my question will become is: are there pitfulls to using Application.get_env(...) in this case?

Yes. That module attribute @my_cfg_section will be evaluated at compile time only. So if you run your program at a later time, with a different env var, that module attribute will not have the change.

Consider a function instead…

defmodule MyApp.M1 do

  def my_cfg_section do
    Application.get_env(:my_app, :my_section)
  end

end
1 Like