В момента изграждам чатбот, използвайки 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 едновременно?
start_polling
? Можете ли да публикувате пълния код на този модул? - person Dogbert   schedule 16.10.2017call
от другcall
илиcast
. Тъй като наведнъж се обработва само едно съобщение, второто повикване няма да се изпълни, преди текущото да излезе и това води до изчакване. - person Dogbert   schedule 16.10.2017