Hey all,
Elixir noob here and first time working with external apis with it. I’m using HTTPoison and later plan to use Oban to run things in the background but not entirely sure on the following:
- How to handle multiple requests?
- Should I hide away the logic in the HTTPoison.Base wrapper?
- How to handle errors?
So here’s my code where I’ve inlined some comments to highlight my some of my thoughts.
HTTPoison wrapper:
defmodule Fin.Wallets.Swyftx do
use HTTPoison.Base
# Not sure what to return here. The raw response? Just the token? A tuple?
# What do I do if the response is an error?
def get_token(api_key) do
case __MODULE__.post("/auth/refresh/", %{apiKey: api_key}) do
{:ok, %{body: %{"accessToken" => token}}} -> {:ok, token}
response -> response
end
# alternatively no case needed?
# {:ok, %{body: %{"accessToken" => token}}} =
# __MODULE__.post("/auth/refresh/", %{apiKey: api_key})
#
# token
end
# Also not sure what to return here. The raw response? Just the token? A tuple?
# What do I do if the response is an error?
def get_orders(api_key) do
{:ok, token} = get_orders(api_key)
{:ok, %{body: %{"orders" => orders}}} =
__MODULE__.get("/orders/?limit=-1", Authorization: "Bearer #{token}")
orders
end
# HTTPoison overrides
def process_request_url(url) do
"https://api.swyftx.com.au" <> url
end
def process_request_headers(headers) do
["Content-Type": "application/json"] ++ headers
end
def process_request_body(%{} = body) do
Jason.encode!(body)
end
def process_request_body(body) do
body
end
def process_response_body(body) do
Jason.decode!(body)
end
end
Context module consuming the HTTPoison wrapper:
defmodule Fin.Wallets do
import Ecto.Query, warn: false
alias Fin.Repo
alias Fin.Wallets.Wallet
alias Fin.WalletTxns
alias Fin.Wallets.Swyftx
# Approach 1
# Without abstracting away some of the logic. Looks very verbose
# How should I be handling errors here?
def sync_swyftx(wallet) do
{:ok, %{body: %{"access_token" => token}}} =
Swyftx.post("/auth/refresh/", %{apiKey: wallet.api_key})
{:ok, %{body: %{"orders" => orders}}} =
Swyftx.get("/orders/?limit=1", Authorization: "Bearer #{token}")
# what happens if create_wallet_txn fails? How to handle this?
Enum.each(orders, fn order ->
WalletTxns.create_wallet_txn(wallet, order)
end)
end
# Approach 2
# Abstracting hitting the auth endpoint and functions for each endpoint
# How shold I be hanlding errors here?
def sync_swyftx(wallet) do
orders = Swyftx.get_orders(wallet.api_key)
# what happens if create_wallet_txn fails? How to handle this?
Enum.each(orders, fn order ->
WalletTxns.create_wallet_txn(wallet, order)
end)
end
end
Any help appreciated