Elixir fsm и Exactor долго не отвечают

В настоящее время я создаю чат-бота, используя Nadia, fsm и Exactor. Я пытаюсь смоделировать каждый разговор пользователя как конечный автомат, чтобы иметь ссылку на каждое состояние, в котором в данный момент находится каждый пользователь, и использовать кеш, чтобы иметь ссылку между идентификатором чата пользователей и его соответствующим идентификатором fsm, который они используют.

Я основывал свой дизайн на этом руководстве< /а>

Следующий фрагмент создает pid, но он зависает всякий раз, когда я пытаюсь перейти в следующее состояние (опрос).

  defp create(id) do
    {:ok, pid} = start_link()
    Cache.get_or_create(:teleid2pid, id, pid)
    IO.inspect "Changing to polling"
    start_polling(pid, id)
    pid
 end

def pid_or_create(id) do
  pid = Cache.get_value(:teleid2pid, id)
  case  pid do
    nil -> create(id)
     _ -> pid
    end
 end

Я создаю возможные события, используя следующий код на основе примера, найденного на странице github библиотеки fsm.

  @one_arity_events [:start_polling, :edit_info, :update_db]
  for event <- @one_arity_events do
    defcall unquote(event)(data), state: fsm do
      FlowFsm.unquote(event)(fsm, data)
      |> new_state
    end
  end

И для этого конкретного примера это событие, которое я вызываю

  defstate start do
     defevent start_polling(id) do
     next_state(:polling, get_user_info(id))
   end
 end

Но функция get_user_info не вызывает замедления. Это пример с использованием iEx.

  iex(1)> alias TelegramBot.FsmServer
  TelegramBot.FsmServer
  iex(2)> alias TelegramBot.FlowFsm
  TelegramBot.FlowFsm
  iex(3)> pid = FsmServer.pid_or_create("1")
  [debug] QUERY OK source="users" db=2.7ms decode=2.6ms
  "Changing to polling"
   ** (exit) exited in: GenServer.call(#PID<0.334.0>, {:start_polling,"1"}, 5000)
  ** (EXIT) time out
 (elixir) lib/gen_server.ex:774: GenServer.call/3
 (backend) 
 lib/backend/telegram_chatbot/fsm/fsm_server.ex:19: 
 TelegramBot.FsmServer.create/1
 iex(3)> pid = FsmServer.pid_or_create("1")
 #PID<0.334.0>
 iex(4)> FsmServer.state(pid)
:polling
iex(5)> FlowFsm.get_user_info("1")        
%{db_id: 1, telegram_id: "1"}

Структура данных FSM работает сама по себе, если я вызываю ее без использования FsmServer.

Что может быть причиной такого огромного отставания? Или еще лучше, как я могу управлять несколькими экземплярами FSM одновременно?


person user2070502    schedule 16.10.2017    source источник
comment
Похоже на тупик. Что делает start_polling? Можете ли вы опубликовать полный код этого модуля?   -  person Dogbert    schedule 16.10.2017
comment
Я только что обновил его, добавив дополнительную информацию и добавив этот hastebin модуля FsmServer и структуру данных Fsm. hastebin.com/simetibave.sql   -  person user2070502    schedule 16.10.2017
comment
Я никогда не использовал ExActor, поэтому синтаксис для меня чужд, но эта проблема обычно возникает, если вы создаете GenServer call из другого call или cast. Поскольку одновременно обрабатывается только одно сообщение, второй вызов не будет выполнен до завершения текущего, что приводит к тайм-ауту.   -  person Dogbert    schedule 16.10.2017
comment
О, это на самом деле мне очень помогло, я обновлю вопрос с изменением, которое устранило проблему. Спасибо   -  person user2070502    schedule 16.10.2017


Ответы (1)


Я вызывал genserver внутри genserver, поэтому он оказался в тупике, как предложил Догберт, чтобы исправить это, я изменил start_link и создал такую ​​​​функцию

defstart start_link(id), do: initial_state(create_fsm(id))

defp create(id) do
  {:ok, pid} = start_link(id)
  Cache.get_or_create(:teleid2pid, id, pid)
  pid
end

defp create_fsm(id) do
  FlowFsm.new
  |> FlowFsm.start_polling(id)
end
person user2070502    schedule 16.10.2017