Empty attribute value in release

I have a weird issue; I compute a value read form the Application and store it as an attribute.

So I have a function in Tools:

# Module Tools
def current_version(),
    do: Application.spec(:logfwd, :vsn) |> to_string()

The key :vsn obviously exists, or spec() would crash.

In a different module I have:

# module Apis
@version Tools.current_version()

def dump_version(), do: @version

In release mode, on my machine (Max, Elixir 1.13.4) I call dump_version() and I get “0.7.14”, while on a Linux server (release compiled locally, same sources) I get

iex(logfwd@bqm1)7> Apis.dump_version
""
iex(logfwd@bqm1)8> Tools.current_version
"0.7.14"

What gives? I’m puzzled.

Edit: I see that spec() says that it will return nil if the application is not loaded, but why should then return the correct value (and not nil) on my development box?

The second one is from an attribute and evaluated at compile-time, think of @ attributes as replacement of the value it contains in the code, while your first variant is at runtime.

1 Like

Yes that was the idea - evaluate once.

It’s not about only evaluate once, it’s about when to evaluate. Attributes are evaluated at compile-time, in this case the application logfwd is not loaded and you cannot get its version, I think you can load it manually though.

2 Likes

In the end I was able to fetch it trough:

       Mix.Project.config()[:version]

And this always works - I’m still puzzled as why the applications seems to be loaded in one case an not the other.

If logfwd is the name of your app, then it makes perfect sense, it can’t display your application version at compile-time as it is not compiled yet.

One thing you have to be careful with: mix will not be available once you release the application, so the.call has to be evaluated at compile-time!

If you don’t understand this behaviour yet, read about elixir metaprogramming, it is a rather complex subject and I wish there was more accesible material about it, the way I learned and understood it is by reading Metaprogramming by Chris McCord, a very good learning resource.

Yes - I wonder why it works at all on my machine, in a release. I would say it was not supposed to work - the application is just not there.

Thanks for the pointer - I did read that book myself and have worked with Clojure for 10 years or so, so I think I’m pretty familiar with macros and macroexpansion.

1 Like

Have you used the same elixir/otp versions? maybe there were some internal changes in config loading in newer versions.

In fact it works on 1.13.4/OTP25 (Mac) but it does not on 1.13.4/OTP24 (Linux)

1 Like