rogach
How to: Tweak mix release to work with hot code reloading
I’ve spent some time understanding how to do hot code reloading with releases built using mix release, and here I’d like to detail the steps needed, in hopes that it will help someone.
So, in order to make hot-reloadable release you need:
- Write an appup file (the Erlang’s Appup cookbook is a great resource for that: Appup Cookbook — Erlang System Documentation v27.0.1).
- Tweak the release generated by
mix release, by copying the .rel & .appup files into expected places and generating the relup file. This can be done by hand, but I’ve wrote a simple function that can do that right inside themix releasetask:
def project do
[
releases: [
app_name: [
include_executables_for: [:unix],
steps: [:assemble, &release_fixup_step/1, :tar],
],
],
...
]
end
defp release_fixup_step(release) do
releases_dir = Path.join(release.path, "releases")
rel_file = Path.join([releases_dir, release.version, "#{release.name}.rel"])
:ok = :release_handler.create_RELEASES(releases_dir, rel_file, [])
# Yes, we have three copies of a same file in the same place.
# This is necessary to appease the release_handler.
File.cp!(rel_file, Path.join([releases_dir, release.version, "#{release.name}-#{release.version}.rel"]))
File.cp!(rel_file, Path.join([releases_dir, "#{release.name}-#{release.version}.rel"]))
# Copy appup file into the correct location and generate the relup.
appup_file = Path.join("appups", "#{release.version}.appup")
if File.exists?(Path.join("appups", "#{release.version}.appup")) do
File.cp!(
appup_file,
Path.join([release.path, "lib", "#{release.name}-#{release.version}", "ebin", "#{release.name}.appup"])
)
{:ok, appup} = :file.consult(appup_file)
[{appup_release_version, [{version_up_from, _}], [{version_down_to, _}]}] = appup
if appup_release_version != to_charlist(release.version) do
raise "Unexpected version in appup: #{appup_release_version} (expected #{release.version})"
end
if version_up_from != version_down_to do
raise "Unexpected versions in appup instructions: #{version_up_from} != #{version_down_to}"
end
:systools.make_relup(
~c"#{release.name}-#{release.version}",
[~c"#{release.name}-#{version_up_from}"],
[~c"#{release.name}-#{version_down_to}"],
path: [to_charlist(Path.join(release.path, "releases/*")), to_charlist(Path.join(release.path, "lib/*/ebin"))],
outdir: to_charlist(release.version_path)
)
end
release
end
Now, after running mix release you will get a release archive in _build/<env>/app_name-<version>.tar.gz.
- Copy this archive into the
releases/directory of your running release. - Connect to the Iex shell of the running release.
- Carefully run the commands:
:release_handler.unpack_release(~c"app_name-<version>")
:release_handler.install_release(~c"<version>")
:release_handler.make_permanent(~c"<version>")
Popular in Guides/Tuts
Hello all!
For those wanting to try your hands at Elixir / Phoenix, I wrote a comprehensive tutorial on doing a simple JSON API with sai...
New
I wrote a small article on how to use current_user with coherence on Phoenix. There are already a couple of blogposts about it but I thin...
New
The EEF’s Security WG has released the first public draft of the Secure Coding and Deployment Hardening Guidelines for BEAM languages.
“...
New
In the process of developing a Phx-based multiplayer experience, I found myself with so many browser tabs open with Elixir gaming resourc...
New
I'm writing up this quick "How to" because what I thought was going to be an easy implementation of a Plug to validate a webhook request ...
New
This is not a question, but a post for anyone who may need it in the future. Sometimes some browsers may mangle the filename if it’s non-...
New
For those of you who might be interested in using ZeroMQ in Elixir, I converted the Erlang examples in the ZeroMQ “zguide” to Elixir. I ...
New
Install web-mode and mmm-mode first and put this in your config file:
(require 'mmm-mode)
(require 'web-mode)
(setq mmm-global-mode 'may...
New
pipe into case? I use that fairly frequently…unless I’m misunderstanding what you’re wanting…could be… its still very early…
str = "Hell...
New
I’ll post this here, It might help someone in the future.
Feedback is greatly appreciated.
I use it with direnv on NixOS, It should wor...
New
Other popular topics
Hi everyone!
I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
After calling mix ecto.create I get this error:
17:00:32.162 [error] GenServer #PID<0.412.0> terminating
** (Postgrex.Error) FATAL...
New
Hi! May someone helps me, please!
I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
Phoenix 1.4.0 released
Phoenix 1.4 is out! This release ships with exciting new features, most notably
with HTTP2 support, improved deve...
New
Here are few pieces of (common) Linux knowledge that we use for reasonably small one server apps. We use Ubuntu but this should work for ...
New
I am trying to run a deploy with docker and I successfully runned with this command:
docker build -t romenigld/blog-prod .
but when I t...
New
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New







