Skip to content

Instantly share code, notes, and snippets.

@AndrewDryga
Created May 13, 2018 16:37
Show Gist options
  • Save AndrewDryga/88caac1a4d422e6c42fa0cf3b36fb931 to your computer and use it in GitHub Desktop.
Save AndrewDryga/88caac1a4d422e6c42fa0cf3b36fb931 to your computer and use it in GitHub Desktop.
Sage: Booking example
defmodule BookingApp.Billing do
def authorize_card(%{exchange_rate: exchange_rate}, %{"card_token" => card_token, "total" => total}) do
{:ok, authorization} = authorize(card_token, total * exchange_rate)
end
def cancel_card_authorization(_effect_to_compensate, effects_to_compensate, _name_and_reason, %{"card_token" => card_token}) do
with {:ok, authorization} <- Map.fetch(effects_to_compensate, :authorization) || fetch_authorization_for_card(card_token) do
:ok = cancel_authorization(authorization)
end
end
def charge_authorization(%{authorization: authorization}, _attrs) do
# ...
end
def refund_payment(_effect_to_compensate, effects_to_compensate, _name_and_reason, %{"card_token" => card_token}) do
# ...
end
defp authorize(_card_token, _total_eur), raise "Not Implemented"
defp cancel_authorization(_authorization), raise "Not Implemented"
defp fetch_authorization_for_card(_card_token), raise "Not Implemented"
end
defmodule BookingApp.Cache do
# Not implemented
def persist(table, key, value), do: :ok
def fetch(table, key, value), do: {:ok, 1}
end
defmodule BookingApp.CurrencyExchange do
def fetch_currency_exchange_rates(_effects_so_far, %{"base_currency" => base_currency}) do
with {:ok, exchange_rates} <- fetch_eur_exchange_rates_to(base_currency, ttl: 30_000) do
BookingApp.Cache.persist(:eur_exchange_rates, base_currency, exchange_rates)
{:ok, exchange_rates}
end
end
def currency_exchange_rates_circuit_breaker(_effect_to_compensate, _effects_so_far, name_and_reason, %{"base_currency" => base_currency}) do
# When error occured on current stage and there is a cache for exchange rates,
# it's safe to proceed with this cached value
with {:currency_exchange_rates, _reason} <- name_and_reason,
{:ok, exchange_rates} <- BookingApp.Cache.fetch(:eur_exchange_rates, base_currency) do
{:continue, exchange_rates}
else
_ -> :ok
end
end
defp fetch_eur_exchange_rates_to(_base_currency), do: 1
end
defmodule BookingApp.Sage do
import Sage
alias BookingApp.{Billing, Hotels, Cars, Flights, Repo}
@spec create_and_subscribe_user(attrs :: map()) ::
{:ok, last_effect :: any(), all_effects :: map()} | {:error, reason :: any()}
def create_booking(attrs) do
new()
|> run(:currency_exchange_rates, &fetch_currency_exchange_rates/2, &currency_exchange_rates_circuit_breaker/4)
|> run(:authorize_card, &Billing.authorize_card/2, &Billing.cancel_card_authorization/4)
|> run_async(:book_hotel, &Hotels.book/2, &Hotels.cancel_booking/4)
|> run_async(:book_car, &Cars.book/2, &Cars.cancel_booking/4)
|> run_async(:book_flight, &Flights.book/2, &Flights.cancel_booking/4)
|> run(:email_confirmation, &send_email_confirmation/2)
|> run(:charge_card, &Billing.charge_card/2, &Billing.refund_payment/4)
|> transaction(Repo, attrs)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment