Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Handling external APIs with Elixir - Alex Rozumii

66 views

Published on

Lightning talk - Elixir Club 8
Peremoga Space, Kyiv
21.10.2017

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Handling external APIs with Elixir - Alex Rozumii

  1. 1. HANDLING EXTERNAL APIS WITH ELIXIR ALEX ROZUMII
  2. 2. ТЕКСТ WHY? ▸ Because: ▸ External API fail (50x) ▸ Network fails ▸ Have rate limits
  3. 3. TelegramInterface.pull_messages(Keyword.get(state, :offset, 0)) Enum.each(items, fn(update) -> case update do %Nadia.Model.Update{message: %Nadia.Model.Message{date: the_date}} -> #IT WORKS _ -> Rollbax.report() end end end
  4. 4. case Dota.live_league_games do {:ok, curr_state} -> # REAL LOGIC {:noreply, tick(prev_state, curr_state)} {:error, %Nadia.Model.Error{reason: :connect_timeout}} -> Process.send_after(self, :timer_event, @wait_ms_before_next_polling_error) {:noreply, tick(prev_state, prev_state)} {:error, {:error, %HTTPoison.Error{id: nil, reason: _reason}}} -> Process.send_after(self, :timer_event, @wait_ms_before_next_empty_response) {:noreply, tick(prev_state, prev_state)} {:error, {:ok, %HTTPoison.Response{status_code: 500}}} -> Process.send_after(self, :timer_event, @wait_ms_before_next_500_error) {:noreply, tick(prev_state, prev_state)} end
  5. 5. ТЕКСТ HOW? ▸ OTP ▸ Agents ▸ Behaviours
  6. 6. defmodule Telegram.MessageQueue do def start_link do Agent.start_link(fn -> [] end, name: __MODULE__) end # @doc Flushes all existing records def flush! do Agent.cast(__MODULE__, fn(_) -> [] end) end # @doc Pushes message for given receiver to queue def push_message(tlg_id, message, opts) do item = {tlg_id, message, opts} # Agent.get(GosuObs.Telegram.MessageQueue, fn set -> set end) Agent.update(__MODULE__, &( [item | &1 ])) end # @doc Gets a top message, grouped if possible def pull_top_message do Agent.get_and_update(__MODULE__, fn queue -> case List.last(queue) do nil -> {nil, []} msg -> end end end end
  7. 7. def handle_info(:timer_event, state) do case Telegram.MessageQueue.pull_top_message do {tlg_id, message, opts} -> case send_message(tlg_id, message, opts) do :ok -> Process.send_after(self, :timer_event, @wait_ms_before_next_message_send) nil :error -> Process.send_after(self, :timer_event, @wait_ms_before_next_message_send) nil :wait -> Process.send_after(self, :timer_event, @wait_ms_before_next_message_send_limit) nil :retry -> Process.send_after(self, :timer_event, @wait_ms_before_next_message) GosuObs.Telegram.MessageQueue.push_message(tlg_id, message, opts) end {:noreply, state} nil -> Process.send_after(self, :timer_event, @wait_ms_before_next_message_pull) {:noreply, state} end end
  8. 8. defp send_message(t, message, opts) do case Nadia.send_message(t, message, opts) do {:ok, _result} -> :ok {:error, %Nadia.Model.Error{reason: "Please wait»}} -> :wait result -> Rollbax.report() :retry end end
  9. 9. THANKS!

×