2017-10-16 170 views
0

我目前正在使用Nadia,fsm和Exactor構建聊天機器人。我試圖將每個用戶對話建模爲一個有限狀態機,以便引用每個用戶當前所處的每個狀態,並使用一個緩存在用戶聊天ID與其所使用的fsm的相應pid之間引用。Elixir fsm和Exactor需要很長時間才能做出反應

我根據我的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"} 

FSM的數據結構的工作原理本身,如果我把它叫做沒有一個例子利用FsmServer。

什麼可能導致這種大規模滯後? 或者更好的是,我怎樣才能同時管理多個FSM的實例呢?

+0

貌似[死鎖](HTTPS ://en.wikipedia.org/wiki/Deadlock)。 'start_polling'是做什麼的?你能發佈這個模塊的完整代碼嗎? – Dogbert

+0

我剛剛更新了一些更多的信息,並添加了FsmServer模塊和Fsm數據結構的這個hastebin。 https://hastebin.com/simetibave.sql – user2070502

+1

我從來沒有使用過ExActor,所以語法對我來說是陌生的,但是如果你在另一個'call'或'cast '。由於每次只處理一條消息,因此第二次調用在當前消息退出並導致超時之前不會執行。 – Dogbert

回答

1

我打電話的genserver的genserver的內部,它在一個死鎖最終成爲Dogbert建議,要解決這個問題我修改了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 
相關問題