Erlang и Relx

21/08/2014

За все свое время знакомства с Erlang мне не нравилось что в нем почти нет CoC, особенно это касалось релизов. Есть мануалы для rebar, можно сделать ручками, но нельзя просто взять и rebar deploy. Эту проблему хочется решить, хотя бы для простых проектов.

Чтобы не разгребать кучу bash скриптов и не читать мануалы по ребару, можно воспользоваться утилитой Relx — она позволяет быстро собрать релиз, обновление и упаковать все это в архив .tar.gz; все это с минимальными настройками и почти без мануалов. Сама утилита очень простая, но мне ее для своих проектов хватает за глаза.

Приложенька

Для тестов нам надо создать простейшее приложение, пусть это будет key-value база данных.

В relx.config мы указываем версию релиза с его названием и зависимостями, в нашем случае это dummy первой версии и sasl для горячего обновления кода.

Чтобы подробнее узнать про конфигурацию relx можно посмотреть этот пример, там все доступные опции приведены с комментариями.

Соберем первую версию:

# скомпилируем код приложения
$ ./rebar compile
# создадим первый релиз
$ ./relx release
# стартуем ноду
$ _rel/dummy/bin/dummy start
# подключаемся
$ _rel/dummy/bin/dummy remote_console

И немного поиграемся:

(dummy@127.0.0.1)1> dummy_db:version().
1
(dummy@127.0.0.1)2> dummy_db:get(a).
not_found
(dummy@127.0.0.1)3> dummy_db:set(foo, bar).
{ok,foo,bar}
(dummy@127.0.0.1)4> dummy_db:get(foo).
{ok,bar}

Как видим - все работает. Консоль можно не закрывать, она понадобится дальше. Поменяем ответ функции dummy_db:get(key) когда ключа не существует с not_found на {not_found, key} и обновим все это с hot code reloading, изменив версию базы данных.

Обновляем

Код обновленного приложения лежит в теге v2. Мы обновили код kvdb, добавили .appup и пару строк о второй версии для relx: v1…v2. Для горячего обновления кода сделаем следующее:

# снова компилируем
$ ./rebar compile
# собираем релиз, relup файл упаковываем в .tar.gz,
# чтобы можно было загружать на сервер
$ ./relx release relup tar
# здесь по идее нам надо было загрузить наш архив на сервер в папку с релизами
# _rel/<app_name>/releases/<new_version>/<app_name>.tar.gz
# но мы все делаем на локальной ноде, поэтому просто копируем
$ cp _rel/dummy/dummy-0.0.2.tar.gz _rel/dummy/releases/0.0.2/dummy.tar.gz
# обновляем приложение
$ _rel/dummy/bin/dummy upgrade "0.0.2/dummy"

Если все обновилось, то можно вернуться в нашу коноль и проверить обновление:

% проверим версию
(dummy@127.0.0.1)5> dummy_db:version().
2
% старые данные
(dummy@127.0.0.1)6> dummy_db:get(foo).
{ok,bar}
% и код ответа
(dummy@127.0.0.1)7> dummy_db:get(a).
{not_found,a}

Задача решена :)