Elixir fsm和Exactor需要很长时间才能做出回应

时间:2017-10-16 03:15:03

标签: elixir otp fsm

我目前正在使用Nadia,fsm和Exactor构建聊天机器人。我试图将每个用户对话建模为有限状态机,以便参考每个用户当前所处的每个状态,并使用缓存在用户聊天ID和其对应的fsm之间进行参考。 ;重新使用。

我的设计基于this tutorial

以下代码段会创建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

我根据fsm library's github page

上的示例使用以下代码创建可能的事件
  @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"}

如果我在不使用FsmServer的情况下调用它,FSM数据结构就可以自行运行。

可能导致这种大规模滞后的原因是什么? 或者更好的是,我如何同时管理多个FSM实例?

1 个答案:

答案 0 :(得分:1)

我在genserver里面调用了genserver,所以它最终出现在Doglock建议的死锁中,为了解决这个问题,我修改了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