Castle

Hot-code upgrade support for Elixir Releases.

Castle provides build and runtime support for the generation of releases that correctly support hot-code upgrades. This includes:

Installation

The package can be installed by adding castle to your list of dependencies in mix.exs:

def deps do
[
{:castle, "~> 0.1.0"}
]
end

Integration

Castle integrates into the steps of the release assembly process. It requires that the Castle.pre_assemble/1 and Castle.post_assemble/1 functions are placed around the :assemble step, e.g.:

defp releases do
[
myapp: [
include_executables_for: [:unix],
steps: [&Castle.pre_assemble/1, :assemble, &Castle.post_assemble/1, :tar]
]
]
end

Build Time Support

The following steps shape the release at build-time:

Pre-assembly

In the pre-assembly step:

The system is then assembled under the :assemble step as normal.

Post-assembly

In the post-assembly step:

Runtime Support

At runtime, the script in the bin folder will intercept any calls to start, start_iex, daemon and daemon_iex and bring up an ephemeral node to generate sys.config by merging build.config with the results of evaluating runtime.exs and any Config Providers.

Additionally, this ephemeral node will create the RELEASES file if it does not already exist.

Release Management

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:

The Appup Compiler

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:

  1. Write a file, in Elixir form, describing the application upgrade. e.g.:
    # 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, []}}
    ]}
    ]
    }
    This file will typically be checked in to SCM.
  2. 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

Relup Generation

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.