Reloading a dependency which has new modules after hot code deploy

I just did an edeliver upgrade to my staging server. One of the changes is an updated internal dependency (so the mix.lock file has been changed).

After upgrading the dependency does not seem to have been updated. At least the changes are not available when I attach to the running release. The dependency is downloaded to the server. I can see it’s updated on the filesystem. But within the running release, I can’t access the new modules of the dependency.

Do I have to do anything special for this updated dependency to be loaded? Is it even possible to do without restarting the application?

I’ve tried reloading it using r/1 but no luck. The mix.exs version of the dependency was changed as part of this updated. But I’m not sure it’s relevant since it’s an internal dependency.

Any help is much appreciated.

Definitely going to need more details. But from how you describe things, it does not seems like the upgrade was installed, only unpacked. Were any other changes taking effect?

If no changes at all were applied, then it sounds like the release was only unpacked, not installed. You could log on to the production host and run bin/myapp upgrade <target_version> to see if any error is produced. You can also run cat <deploy_root>/releases/start_erl.data to see what release is active (the version is the 2nd column), and you can look at <deploy_root>/releases/RELEASES to see what versions of dependencies are in that release.

Assuming you updated your mix.lock, then the dependency should have been upgraded (as long as that mix.lock change made it to your build server). I don’t know how edeliver works internally, but I don’t think there is anything it could have done to break that.

Hi @bitwalker

Thanks for the reply.

Were any other changes taking effect?

Yes all other changes took effect in my application. The only thing missing is the internal dependency (hosted on a private Git Repository).

run bin/myapp upgrade <target_version> to see if any error is produced

bin/myapp upgrade <target_version> prints that the version is already unpacked, installed & set permanent

run cat <deploy_root>/releases/start_erl.data

cat myapp/releases/start_erl.data shows the correct version

you can look at <deploy_root>/releases/RELEASES to see what versions of dependencies are in that release

<deploy_root>/releases/RELEASES shows the correct version of the dependency.

I find this very odd. Because I’ve done this many times before without issues. I must have forgotten something in the deployment process.

Sounds like everything is right then, but that the version of the dep you thought contained the new code actually doesn’t in the source repository - I would validate that first. If it is in the repo at the version in your mix.lock (on the build server, not on your local machine), then I would take a look in <deploy_root>/lib/<dep>-<version>/ebin and see if the BEAM files are there. If they are, then those modules must be loaded. You can try running :code.which(ModuleName) in a remote shell to see if the code loader can find it, and where on disk it is.

Hi

Thanks for your advice and help so far. I’m learning new things today :slight_smile:

Sounds like everything is right then, but that the version of the dep you thought contained the new code actually doesn’t in the source repository - I would validate that first.

I’ve double checked and the new code is in the source repository. It is also downloaded onto the server and located in the edeliver tmp folder.

then I would take a look in <deploy_root>/lib/-/ebin and see if the BEAM files are there

They certainly are

You can try running :code.which(ModuleName)

So this is actually interesting. Because doing this with the module name of the module missing shows that it is looking for the dep in the deploy_root/lib/~/ebin of the previous version of the dependency. Is there any way I can force it to look at the right now?

I’ve just deployed a new upgrade and I must have messed something up trying to solve the issue ealier. Now when doing :code.which(ModuleName) it returns :in_memory but when doing :code.which(ModuleName.Submodule) it prints the path of for the .beam for that submodule in the new version of the dependency.

Is there anyway to load that .beam file into the running instance?

Is there anyway to load that .beam file into the running instance?

Holy cow. I found :code.load_file in the erlang docs. It seems to work

Can you post the relup file from the release directory? I’d like to figure out why it didn’t apply the upgrade. I’m assuming this was a hot upgrade right? If not, what version of Distillery are you running?

1 Like

I ask the above, because when you restart the release it will go back to the old code probably

1 Like

Can you post the relup file from the release directory? I’d like to figure out why it didn’t apply the upgrade. I’m assuming this was a hot upgrade right?

Sure. But I’m not sure what file you’re asking for. Could you be more specific?

I’m assuming this was a hot upgrade right?

Correct

If not, what version of Distillery are you running?

I’ll give you the version anyway :slight_smile:
Destillery: 1.5.2
Edeliver: 1.4.4

The file is just called relup, and will be in the versioned release directory, i.e. <deploy_root>/releases/<version>/relup>

{"1.0.90+fix-staging-bitbucket-api-462117d",
 [{"1.0.71+fix-staging-bitbucket-api-9d514aa",[],
   [{load_object_code,{bitbucket_api,"0.6.0",['Elixir.BitbucketApi.Teams']}},
    {load_object_code,{pace,"1.0.90+fix-staging-bitbucket-api-462117d",
                            ['Elixir.Pace.Endpoint','Elixir.Pace.Gettext',
                             'Elixir.Pace.User']}},
    point_of_no_return,
    {load,{'Elixir.BitbucketApi.Teams',brutal_purge,brutal_purge}},
    {load,{'Elixir.Pace.Endpoint',brutal_purge,brutal_purge}},
    {load,{'Elixir.Pace.Gettext',brutal_purge,brutal_purge}},
    {load,{'Elixir.Pace.User',brutal_purge,brutal_purge}}]}],
 [{"1.0.71+fix-staging-bitbucket-api-9d514aa",[],
   [{load_object_code,{pace,"1.0.71+fix-staging-bitbucket-api-9d514aa",
                            ['Elixir.Pace.Endpoint','Elixir.Pace.Gettext',
                             'Elixir.Pace.User']}},
    point_of_no_return,
    {remove,{'Elixir.BitbucketApi.Teams',brutal_purge,brutal_purge}},
    {purge,['Elixir.BitbucketApi.Teams']},
    {load,{'Elixir.Pace.Endpoint',brutal_purge,brutal_purge}},
    {load,{'Elixir.Pace.Gettext',brutal_purge,brutal_purge}},
    {load,{'Elixir.Pace.User',brutal_purge,brutal_purge}}]}]}.

Elixir.BitbucketApi.Teams is the new module