LINUX.ORG.RU

а есть тут специалисты по elixir и gen_stage?

 


0

1

пытаюсь понять проблему, почему на вполне корректный ask еликсировский продюсер ломается. причем где-то у себя внутри

3:30:04.917 [error] GenServer Producer terminating                                                                                                              
* (FunctionClauseError) no function clause matching in GenStage.maybe_producer_cancel/2                                                                         
   (gen_stage 1.1.2) lib/gen_stage.ex:2236: GenStage.maybe_producer_cancel([], %GenStage{buffer: {{[], []}, 0, 10000}, buffer_keep: :last, consumers: %{}, dispa
cher_mod: GenStage.DemandDispatcher, dispatcher_state: {[], 0, nil, false}, events: :forward, mod: Producer, monitors: %{}, producers: %{}, state: 0, type: :pro
ucer})                                                                                                                                                          
   (gen_stage 1.1.2) lib/gen_stage.ex:1938: GenStage.handle_info/2                                                                                              
   (stdlib 3.17) gen_server.erl:695: :gen_server.try_dispatch/4                                                                                                 
   (stdlib 3.17) gen_server.erl:771: :gen_server.handle_msg/6                                                                                                   
   (stdlib 3.17) proc_lib.erl:226: :proc_lib.init_p_do_apply/3                                                                                                  
ast message: {:"$gen_producer", {#PID<26758.1008.0>, #Reference<26758.0.23478.68204>}, {:subscribe, [], [min_demand: 1, max_demand: 5, cancel: 0, manual: false,
partition: 0]}}                                                                                                                                                 
tate: 0                                                                                                                                                         
roducer started                                                                                                                                                 

зарепортили багу https://github.com/ergo-services/ergo/issues/103

если в гошный consumer добавить колбек

func (c *Consumer) HandleCanceled(process *gen.StageProcess, subscription gen.StageSubscription, reason string) gen.StageStatus {
   fmt.Println("canceled with reason", reason)
   return gen.StageStatusOK
}                   

то принтует тот же бектрейс эликсировского no function clause matching. ну это не сильно помогает, просто показывает, что гошный консьюмер ловит смерть продьюсера и причину его смерти.

просто я с эликсиром даже не на «вы». буду признателен за советы как это можно полечить

★★★

См. внимательно, как вызывается функция:

GenStage.maybe_producer_cancel([], %GenStage{...snip...})                                                                                                                

Если предположить, что у человека последняя версия GenStage, то проблема в том, что функция GenStage.maybe_producer_cancel/2 принимает в качестве первого аргумента либо кортеж из двух элементов, либо nil, а в итоге она вызывается с пустым списком, из-за чего и вылетает FunctionClauseError. Сходу сказать, почему так происходит, я не могу, но вангую, что вместо пустого списка в функцию в этом случае надо передавать именно nil. Единственное место, где вызывается эта функция, находится тут, так что оттуда и надо начинать поиски.

theNamelessOne ★★★★★
()
Последнее исправление: theNamelessOne (всего исправлений: 2)
Ответ на: комментарий от theNamelessOne

На таком уровне я читать эликсир умею :). Вопрос, почему он кенселит, да ещё и с ошибкой.

ergo ★★★
() автор топика
Ответ на: комментарий от ergo

Вопрос, почему он кенселит

Он не кенселлит, а maybe кенселит, и судя по коду эта функция вызывается вообще для всех новых подписок, так что «почему» тут ИМХО не совсем правильный вопрос.

да ещё и с ошибкой

В доках написано, что это сообщение приходит прямиком из консьюмера. Т.е. выглядит так, что гошный consumer посылает в качестве поля current (в коде оно называется cancel) пустой список вместо Erlang-атома nil. Почему так происходит, тебе должно быть виднее; на мой (неподготовленный) взгяд вот эта строка выглядит подозрительной: представляет ли (гошный) nil на стороне Erlang/Elixir такое же самое значение, что и etf.Atom("nil") (т.е. Erlang-атом nil)?

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

theNamelessOne ★★★★★
()
Последнее исправление: theNamelessOne (всего исправлений: 2)
Ответ на: комментарий от theNamelessOne

да, все верно. я уже разобрался. ерго nil кодирует как пустой список (это чисто ерланговская тема, не эликсира). в этом же случае ты все правильно написал. нужно было явно атом nil слать.

в любом случае, спасибо большое

ergo ★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.