В настоящее время я создаю чат-бота, используя Nadia, fsm и Exactor. Я пытаюсь смоделировать каждый разговор пользователя как конечный автомат, чтобы иметь ссылку на каждое состояние, в котором в данный момент находится каждый пользователь, и использовать кеш, чтобы иметь ссылку между идентификатором чата пользователей и его соответствующим идентификатором 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