Cowboy handler с вызовами gen_server'ов

200 views
Skip to first unread message

DarkIT

unread,
Jun 5, 2013, 3:46:34 AM6/5/13
to erlang-...@googlegroups.com
Хочется сделать cowboy рест обработчик, который вызывает ассинхронно несколько ген_серверов и потом ждет когда они все отработают.
Логически понятно как сделать, но как это реализовать вопрос.

1. У ген_серверов есть отдельное приложение и супервизор который их порождает, супервизор залинкован на приложение, а то в свою очередь на текущий ерл.
И точно также cowboy имеет свой супервизор, в недрах которого порождаются мои рест обработчики.
Но надо как то связать мой обработчик и созданый ген_сервер чтобы при падении одного завершить другое - как это правильней сделать? Просто создать руками link?

2. И как отсылать ответ из ген_сервера в обработчик, просто через ! оператор?

Paul Peregud

unread,
Jun 5, 2013, 6:01:08 AM6/5/13
to erlang-...@googlegroups.com
Линк симметричен, и поэтому не всегда удобен. Если оба процеса
"temporary" и вам не нужно делать специальную обработку на завершение,
то можете использовать линк. Но я бы все равно использовал
erlang:monitor/2.

2013/6/5 DarkIT <dar...@gmail.com>:
> --
> --
> Страница рассылки: http://groups.google.com/group/erlang-russian
> Новости: http://erlanger.ru
> Чат: xmpp://erl...@conference.jabber.ru
> Чат для оффтопа: xmpp://erlang...@conference.jabber.ru
> Правила, действующие в чате и рассылке:
> http://erlanger.ru/ru/erlang-at-conference-jabber-ru
>
> Написать письмо: erlang-...@googlegroups.com
> Отписаться: erlang-russia...@googlegroups.com
> ---
> Вы получили это сообщение, поскольку подписаны на группу Erlang по-русски.
>
> Чтобы отказаться от подписки на эту группу и перестать получать из нее
> сообщения, отправьте электронное письмо на адрес
> erlang-russia...@googlegroups.com.
> Настройки подписки и доставки писем:
> https://groups.google.com/groups/opt_out.
>
>



--
Best regards,
Paul Peregud
+48602112091

DarkIT

unread,
Jun 5, 2013, 6:13:42 AM6/5/13
to erlang-...@googlegroups.com
Я исхожу из того, что хендлер что ген_сервер если падают то должны проинформировать друг друга, тк они оба должны отработать или нет.

И вопрос еще был - эту связку делать все же руками, а не средствами ОТР через супервизоров?

Paul Peregud

unread,
Jun 5, 2013, 6:26:23 AM6/5/13
to erlang-...@googlegroups.com
Supervisor умеет рестартовать, добавлять и удалять детей. И, по сути,
ничего больше ему уметь и не надо. Отслеживать из воркера других
воркеров вам надо руками.

2013/6/5 DarkIT <dar...@gmail.com>:

DarkIT

unread,
Jun 5, 2013, 3:01:56 PM6/5/13
to erlang-...@googlegroups.com
В догонку вопрос - сделал что cowboy handler делал start_link и запускал ген_сервер. Когда ген_сервер падает то ковбой ловит EXIT, а вот когда наоборот, то ген_сервер вообще никак ничего не ловит и тихо мрет.

Нашел на форуме такой комментарий "Gen_server handles exits from the parent in a special way, assuming that the parent is a supervisor. If the server does *not* trap exits, obviously it doesn't matter, but even when trapping exits, the gen_server will unconditionally exit if it gets an exit from the parent. 
"

Те получается, что корректно зачистить состояние и ресурсы в моем ген_сервере при падении ковбоя никак нельзя?

DarkIT

unread,
Jun 5, 2013, 3:12:38 PM6/5/13
to erlang-...@googlegroups.com

buddy

unread,
Jun 6, 2013, 4:36:12 AM6/6/13
to erlang-...@googlegroups.com
В документации на gen_server говорится:

Module:terminate(Reason, State)

If the gen_server is part of a supervision tree and is ordered by its supervisor to terminate, this function will be called with Reason=shutdown if the following conditions apply:

* the gen_server has been set to trap exit signals, and
* the shutdown strategy as defined in the supervisor's child specification is an integer timeout value, not brutal_kill.

Even if the gen_server is not part of a supervision tree, this function will be called if it receives an 'EXIT' message from its parent. Reason will be the same as in the 'EXIT' message.

Otherwise, the gen_server will be immediately terminated.

Если gen_server не является частью дерева супервизора, то он все равно получит 'EXIT' от предка.
В gen_server.erl есть такое место:

decode_msg(Msg, Parent, Name, State, Mod, Time, Debug, Hib) ->
    case Msg of
        ...
        {'EXIT', Parent, Reason} ->
            terminate(Reason, Name, Msg, Mod, State, Debug);
        ...

Но видимо это произойдет только если будет существовать link с предком, а сам gen_server будет делать trap exit. То есть, я не понимаю, чем это будет отличаться от случая с супервизором. Как-то в документации расплывчато написано.

среда, 5 июня 2013 г., 23:01:56 UTC+4 пользователь DarkIT написал:

Max Lapshin

unread,
Jun 6, 2013, 5:09:03 AM6/6/13
to erlang-...@googlegroups.com
Это очень плохая идея пользоваться link/'EXIT' для мониторинга процессов.

Это системный протокол с очень специфичным поведением. В
пользовательском коде лучше использовать мониторы.

DarkIT

unread,
Jun 6, 2013, 8:32:31 AM6/6/13
to erlang-...@googlegroups.com
В чем плохая? В чем специфичный? (без подвоха вопрос, а для понимания)
Те для меня нуба-ерланга сейчас разница только в том что линк бидиекшин, а монитор односторонний. И мониторы можно вешать по несколько штук.
И если надо чтобы процессы знали друг о друге то делать два симметричных монитора?

DarkIT

unread,
Jun 6, 2013, 8:37:06 AM6/6/13
to erlang-...@googlegroups.com
Я сейчас сделал, что ген_сервер создается через супервизор и потом явно линкуется к ковбой хендлеру.
Но получил странное поведение: http://stackoverflow.com/questions/16955487/cowboy-handler-and-custom-gen-server-link
А именно - хендлер ловит падение ген_сервера как EXIT сообщение - те поведение как надо,
но если падает хендлер то ген_сервер не получает EXIT собщение, а просто  вызывается terminate normal
И сейчас я в непонятке - тк у ген_сервера могут быть дочерние процессы и надо понимать что ковбой упал и дальше можно завершать работу, или же упал дочерний и его можно перезапустить. 

Наверное у меня неправильное восприятие как строится дерево процессов и их воркфлоу жизни - если кто тыкнет носом в ошибки проектирование, буду признателен.

Sergey Prokhorov

unread,
Jun 6, 2013, 9:45:44 PM6/6/13
to erlang-...@googlegroups.com
Не нужно стартовать gen_server напрямую из ковбоя. Если правильно понял, то нужно сделать вот как:
Создать simple_one_for_one супервизор, который умеет стартовать этот ваш gen_server
Из ковбоя делать
Pid = supervisor:start_child(my_sup, [self(), OtherParams...]).
erlang:monitor(...Pid...)
И в gen_server в init делать erlang:monitor(Pid) (Pid приходит в init т.к. вы его передали в start_child)

четверг, 6 июня 2013 г., 16:37:06 UTC+4 пользователь DarkIT написал:

DarkIT

unread,
Jun 7, 2013, 3:08:34 AM6/7/13
to erlang-...@googlegroups.com
Так у меня так и есть, только использую линк и линкую процессы в ковбое, когда получаю pid дитя. 
И при таком раскладе кто-то перехватывает EXIT сообщение и ген_сервер завещается нормально.
Reply all
Reply to author
Forward
0 new messages