Runtime support for hot-code upgrades.
Castle
provides runtime support for hot-code upgrades. In particular, it generates a
valid sys.config
from runtime.exs
and/or other Config Providers
prior to both boot and hot-code upgrade.
It relies on Forecastle for build-time release generation and brings it in as a build-time dependency.
The package can be installed by adding castle
to your list of dependencies in
mix.exs
. For projects that don't define a release, but use the appup
compiler,
it's sufficient to bring Castle
in as a build-time dependency:
def deps do
[
{:castle, "~> 0.3.0", runtime: false}
]
end
For projects that do define one or more releases, Castle
should be brought in
as a runtime dependency:
def deps do
[
{:castle, "~> 0.3.0"}
]
end
Castle
brings in Forecastle
as a build-time dependency.
Build-time integration is done via Forecastle
and more details can be found in its
documentation but, in summary, it will integrate into your release process via the
release assembly process. In particular, it requires that that the Forecastle.pre_assemble/1
and Forecastle.post_assemble/1
functions are placed around the :assemble
step, e.g.:
defp releases do
[
myapp: [
include_executables_for: [:unix],
steps: [&Forecastle.pre_assemble/1, :assemble, &Forecastle.post_assemble/1, :tar]
]
]
end
The script in the bin
folder supports some extra commands to manage upgrades.
Releases, in their tarred-gzipped form, should first be copied to the releases
subfolder on the target system. The following commands can be used to manage
them:
releases
- Lists the releases on the system and their status. Status can be one of the following:- permanent - the release the system will boot into on next restart.
- current - if it exists, represents the current running release. Will be different from the permanent version if a new release has been installed but not yet committed. If no version is listed as current, the permanent version is the currently running version.
- old - if it exists, a previously installed version.
- unpacked - an unpacked version, but not yet installed.
unpack <vsn>
- Unpacks the release called<name>-<vsn>.tar.gz
.install <vsn>
- Installs the new release. This makes the release the current one, but not yet the permanent one. Prior to running the relup,Castle
generates the version specificsys.config
for the new version.commit <vsn>
- Makes the specified release the one the permanent one.remove <vsn>
- Remove an old version from the filesystem. Any files shared with remaining releases are left untouched.
You are responsible for writing the appup
scripts for your application, but Castle
will copy the appup into the ebin
folder
for you. The steps are as follows:
- Write a file, in Elixir form, describing the application upgrade. e.g.:
This file will typically be checked in to SCM.
# You can call the file what you like, e.g. appup.ex, # but you should # keep it away from the compiler paths. { '0.1.1', [ {'0.1.0', [ {:update, MyApp.Server, {:advanced, []}} ]} ], [ {'0.1.0', [ {:update, MyApp.Server, {:advanced, []}} ]} ] }
- Add the appup file to the Mix project definition in mix.exs and add the
:appup
compiler.# Mix.exs def project do [ appup: "appup.ex", # Relative to the project root. compilers: Mix.compilers() ++ [:appup] ] end
Castle contains a mix task, castle.relup
, that simplifies the generation of
the relup file. Assuming you have two unpacked releases e.g. 0.1.0
and 0.1.1
and you wish to generate a relup between them:
> mix castle.relup --target myapp/releases/0.1.1/myapp --fromto myapp/releases/0.1.0/myapp
If the generated file is in the project root, it will be copied during post-assembly to the release.