Elixir fsm и Exactor отнема много време, за да отговорят

В момента изграждам чатбот, използвайки Nadia, fsm и Exactor. Опитвам се да моделирам всеки потребителски разговор като крайна машина, за да има препратка към всяко състояние, в което всеки потребител се намира в момента, и да използвам кеш, за да има препратка между потребителския чат идентификатор и съответния му pid на 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, така че се озова в Deadlock, както предложи 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
person user2070502    schedule 16.10.2017