defmodule YaloTestConversation.Worker do @moduledoc """ Documentation for Worker """ require Logger use GenServer def start_link(bot, messages, activity, id) do GenServer.start_link(__MODULE__, [bot, messages, activity, id], name: String.to_atom(id)) end def init([bot, messages, activity, id]) do start = NaiveDateTime.utc_now() state = %{ id: id, bot: bot, messages: messages, start: start, activity: activity, attempts: 0 } Logger.info("INIT WORKER #{inspect(state.id)}") send(self(), :send_message) {:ok, state} end def send_message(current_message, state) do env = Application.get_all_env(:yalo_test_conversation) Logger.info("SENDING.... #{inspect(current_message["message"])}") headers = [{"Content-Type", "application/json"}] IO.inspect( "#{env[:hooks_proxy]}/botrunner?callback-url=#{env[:callback_url]}?pid=#{state.id}" ) case HTTPoison.request( "POST", "#{env[:hooks_proxy]}/botrunner?callback-url=#{env[:callback_url]}?pid=#{state.id}", Poison.encode!(current_message["message"]), headers ) do {:ok, %HTTPoison.Response{status_code: 200, body: _body}} -> Logger.info("Sended message to hooks-proxy") timer = Process.send_after(self(), :noresponse, 10 * 1000) Map.merge(state, %{timer: timer}) {:ok, %HTTPoison.Response{status_code: status, body: _body}} -> Logger.error("Not found :( reponse status code: #{status}") timer = Process.send_after(self(), :noresponse, 10 * 1000) Map.merge(state, %{timer: timer}) {:error, %HTTPoison.Error{reason: reason}} -> Logger.error("Is not responding reason: #{reason}") timer = Process.send_after(self(), :noresponse, 10 * 1000) Map.merge(state, %{timer: timer}) end end def handle_info(:noresponse, state) do Logger.info("NORESPONSE") [current_message | messages] = state.messages if state.attempts >= 3 do Logger.info("FINISH") # Report status end_date = NaiveDateTime.utc_now() resolved_at = Integer.to_string(NaiveDateTime.diff(end_date, state.start, :second)) new_state = Map.merge(state, %{ end: end_date, status: "fail", message: current_message["message"], resolved_at: resolved_at }) Logger.error("send to Sentry: #{inspect(new_state.bot)}") {:stop, :shutdown, state} else Logger.error("NO RESPONSE RETRY #{inspect(state.attempts)}") state = %{state | attempts: state.attempts + 1} new_state = send_message(current_message, state) {:noreply, new_state} end end def handle_info(:send_message, state) do Logger.info("SEND MESSAGE") [current_message | messages] = state.messages # enviar mensaje al server con current_activity new_state = send_message(current_message, state) {:noreply, new_state} end def handle_cast({:recieve_message, recieve_msg}, state) do recieve_message = Map.delete(recieve_msg, "pid") Logger.info("RECIEVE MESSAGE #{inspect(recieve_message)}") if Map.get(state, :timer) != nil do Logger.info("Cancel timer") Process.cancel_timer(state.timer) state = Map.delete(state, "timer") end # remove the last message [head | tail] = state.messages [current_message | message_queue] = tail st = %{ bot: state.bot, messages: message_queue, start: state.start, activity: state.activity, id: state.id, attempts: state.attempts } # verificar si es el mensaje esperado en messages[offset] llega Logger.info("CURRENT MESSAGE #{inspect(current_message["message"])}") if message_queue == [] do if recieve_message == current_message["message"] do Logger.info("MESSAGE RECIEVE IS THE EXPECTED") else Logger.error("MESSAGE RECIEVE IS NOT THE EXPECTED") end Logger.info("FINISH") # Report status end_date = NaiveDateTime.utc_now() resolved_at = Integer.to_string(NaiveDateTime.diff(end_date, state.start, :second)) new_state = Map.merge(state, %{ end: end_date, status: "ok", message: "SUCCESS", resolved_at: resolved_at }) {:stop, :shutdown, new_state} else if recieve_message == current_message["message"] do Logger.info("MESSAGE RECIEVE IS THE EXPECTED") [next_message | queue] = message_queue if next_message["senderType"] == "bot" do Logger.info("waiting for other message...") else Logger.info("Send again....") st = send_message(next_message, st) end else Logger.error("MESSAGE RECIEVE IS NOT THE EXPECTED") [next_message | queue] = message_queue st = send_message(next_message, st) end end {:noreply, st} end end