Написал следующее решение:
upgrade() -> gen_server:call({global, ?MODULE}, { upgrade }).
handle_call({ upgrade }, _From, State) ->
code:purge(?MODULE),
compile:file(?MODULE),
code:load_file(?MODULE),
{ reply, ok, State };
Похоже, что этот код делает то, что мне нужно, однако беспокоят
некоторые моменты:
* Не выявится ли каких косяков под настоящей нагрузкой?
* Почему не вызывается code_change?
* Из-за второго пункта меня терзают подозрения, что я что-то сделал не
так, изобрел велосипед к примеру.
Что скажите?
В процессе гугления мне попадались упоминания всяких Erlmakefile и
инструментов для работы с релизами, но для меня это пока сложно,
хотелось бы с мат частью разобраться для начала.
Обновление кода осуществляется в тот момент, когда вызывается функция
с явным указанием модуля:
?MODULE:loop(...)
Поэтому самопальные процессы в которых написан просто
loop(...)
спонтанно дохнут, когда их модуль вытесняется.
Однако в таком простом виде у вас всё свалится, если стейт — рекорд и
он поменялся.
Для этого есть система релизов, которая останавливает все ваши
процессы, вызывает в них code_change и запускает дальше.
Лично я сходу не представляю, как можно взять и написать code_change
так, что бы перенести данные из старого стейта в новый.
Т.е. у меня есть идеи, но я даже не хочу их проверять. Впрочем, у
кого-то это работает, но они никогда не рассказывают, как именно.
Поэтому резюме такое:
1) самый простой способ — make:all([load]). на ноде и сразу получать новый код
2) если рекорд поменялся всё свалится — будьте к этому готовы
А что при этом происходит с другими процессами?
Но ты и под ними меняешь код.
Я создал Emakefile:
{'src/test.erl', [{outdir, "ebin"}]}.
Собрал сервер:
erl -make
Запустил сервер:
erl -noshell -pa ebin -sname test -run test start
Поработал с сервером, теперь решил его обновить. Мне почему-то
казалось, что должно сработать простое erl -make, после чего
виртуальная машина должна увидеть новый beam, подгрузить его и
автоматически переключаться на новый код при вызове
?MODULE:any_function. Но видимо это не так, ибо не работает. Я даже
добавил вызов ?MODULE:dummy.
А как нужно?
7 сентября 2012 г., 14:42 пользователь Anton Fedorov
<datac...@call2ru.com> написал:
> --
> --
> Страница рассылки: http://groups.google.com/group/erlang-russian
> Новости: http://erlanger.ru
> Чат: xmpp://erl...@conference.jabber.ru
> Чат для оффтопа: xmpp://erlang...@conference.jabber.ru
>
> Написать письмо: erlang-...@googlegroups.com
> Отписаться: erlang-russia...@googlegroups.com
>
>
--
С уважением, Александр
Личный блог: http://eax.me/
Мой форум: http://it-talk.org/
Мой Twitter: http://twitter.com/afiskon
Если code_change вызывается ещё в старом модуле, то можно добавить
функцию, которая превращает рекорд в проплист и обратно.
Тогда из старого рекорда мы извлечем данные старым модулем и переложим в новый:
code_change(OldState) ->
OldProplist = state_to_proplist(OldState),
NewState = ?MODULE:proplist_to_state(OldProplist)
Но это только если code_change в старом модуле.
А как она должна увидеть? Дергая раз в секунду на диске все загруженные бимы?
А если они по сети были залиты?
Нет, это безусловно невозможно. Так работают штуки типа sync и
reloader, но лично я ими не пользуюсь.
>
> А как нужно?
>
Написали же: в консоли сделать make:all([load]).
Хоть индуса на такое нанимай.
Разобрался, спасибо! Вот только я надеялся, что code_change() будет
вызываться, но похоже, что он и не должен:
This function is called by a gen_server when it should update its
internal state during a *RELEASE* upgrade/downgrade. (
http://www.erlang.org/doc/man/gen_server.html )
А чтобы произошло обновление релиза, нужно воспользоваться -version
или VSN или может еще чем-то?
7 сентября 2012 г., 15:35 пользователь Max Lapshin
<max.l...@gmail.com> написал:
> Ну вот: поменять структуру рекорда в ets.
> Та же ведь фигня.
>
> --
> --
> Страница рассылки: http://groups.google.com/group/erlang-russian
> Новости: http://erlanger.ru
> Чат: xmpp://erl...@conference.jabber.ru
> Чат для оффтопа: xmpp://erlang...@conference.jabber.ru
>
> Написать письмо: erlang-...@googlegroups.com
> Отписаться: erlang-russia...@googlegroups.com
>
>
--