2017-10-16 8 views
0

現在、ナディア、fsm、Exactorを使用してチャットボットを構築中です。私はすべてのユーザーの会話を有限状態マシンとしてモデル化して、各ユーザーが現在いる各状態の参照を持ち、キャッシュを使用して、ユーザーのチャットIDと使用しているfsmの対応するPIDを参照しようとしています。エリクサーfsmとエキスパクターが反応するまでに時間がかかります

私はthis tutorial

次のスニペットに私のデザインは、それは私が使用して可能性のあるイベントを作成する(ポーリング)

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 

次の状態に移行しようとしたときに立ち往生pidを作成しますが、ベース次のコード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 

に見出され、この特定の例のために、これは、Tである例に基づいて私は

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

のような関数を作成することは、[デッドロック]のように見える、genserverの内側genserverを呼んでいました://en.wikipedia.org/wiki/Deadlock)。 'start_polling'は何をしますか?あなたはこのモジュールの完全なコードを投稿できますか? – Dogbert

+0

私はいくつかの情報でこれを更新し、FsmServerモジュールとFsmデータ構造のこのhastebinを追加しました。 https://hastebin.com/simetibave.sql – user2070502

+1

私はExActorを使ったことがないので、構文はわかりませんが、この問題は通常、別の 'call'または' cast'の中からGenServer 'call'を作ると起こります'。一度に1つのメッセージしか処理されないので、2番目の呼び出しは現在の呼び出しが終了する前に実行されず、結果としてタイムアウトになります。 – Dogbert

答えて

1

Dogbertが示唆したように、それはデッドロックで終わったので、私がhttps(私は、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 
関連する問題