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


Published on

Lightning talk - Elixir Club 8
Peremoga Space, Kyiv

Published in: Technology
  • I like this service ⇒ ⇐ from Academic Writers. I don't have enough time write it by myself.
    Are you sure you want to  Yes  No
    Your message goes here
  • Be the first to like this

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 _ -> 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 -> :retry end end
  9. 9. THANKS!