This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| def book_trip(attrs) do | |
| with {:ok, exchange_rates} <- BillingAPI.fetch_currency_exchange_rates(attrs), | |
| {:ok, card_authorization} <- BillingAPI.authorize_card(exchange_rates, attrs), | |
| {:booking, {:ok, hotel_booking}, _} <- {:booking, HotelsBookingAPI.book_hotel(attrs), []}, | |
| {:booking, {:ok, car_booking}, _} <- {:booking, CarsBookingAPI.book_hotel(attrs), [hotel_booking]}, | |
| {:booking, {:ok, flight_booking}, _} <- {:booking, FlightsBookingAPI.book_hotel(attrs), [hotel_booking, car_booking]}, | |
| :ok <- Mailer.send_email_confirmation(card_authorization, hotel_booking, attrs), | |
| {:charge, {:ok, charge}, _} <- {:charge, BillingAPI.charge_card(card_authorization), [...]} do | |
| {:ok, %{charge: charge, bookings: [hotel_booking, car_booking, flight_booking]}} | |
| else |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| def book_trip(attrs) do | |
| with {:ok, exchange_rates} <- BillingAPI.fetch_currency_exchange_rates(attrs), | |
| {:ok, card_authorization} <- BillingAPI.authorize_card(exchange_rates, attrs), | |
| {:ok, hotel_booking} <- HotelsBookingAPI.book_hotel(attrs), | |
| :ok <- Mailer.send_email_confirmation(card_authorization, hotel_booking, attrs), | |
| {:charge, {:ok, charge}, _} <- {:charge, BillingAPI.charge_card(card_authorization), [hotel_booking]} do | |
| {:ok, %{charge: charge, bookings: [hotel_booking]}} | |
| else | |
| {:charge, {:error, reason], [hotel_booking]} -> | |
| :ok = send_excuse_email(authorization) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| def book_trip(attrs) do | |
| with {:ok, exchange_rates} <- BillingAPI.fetch_currency_exchange_rates(attrs), | |
| {:ok, card_authorization} <- BillingAPI.authorize_card(exchange_rates, attrs), | |
| {:ok, hotel_booking} <- HotelBookingAPI.book_hotel(attrs), | |
| :ok <- Mailer.send_email_confirmation(card_authorization, hotel_booking, attrs), | |
| {:ok, charge} <- BillingAPI.charge_card(card_authorization) do | |
| {:ok, %{charge: charge, bookings: [hotel_booking]}} | |
| end | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| defmodule BookingApp.Booker do | |
| alias BookingApp.{Billing, Users, Hotels, Cars, Flights, Repo} | |
| def create_booking(attrs) do | |
| Sage.new() | |
| |> Billing.authorize_card(attrs) | |
| |> Hotels.maybe_book_hotel(attrs) | |
| |> Cars.maybe_book_car(attrs) | |
| |> Flights.maybe_book_flight(attrs) | |
| |> Users.sign_up() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| defmodule MyApp.Domain.User.SignUp do | |
| def create_and_subscribe_user(attrs) do | |
| Repo.transaction(fn -> | |
| with {:ok, user} <- create_user(attrs), | |
| {:ok, plans} <- fetch_subscription_plans(attrs), | |
| {:ok, charge} <- charge_card(user, subscription), | |
| {:ok, subscription} <- create_subscription(user, plan, attrs), | |
| {:ok, _delivery} <- schedule_delivery(user, subscription, attrs), | |
| {:ok, _receipt} <- send_email_receipt(user, subscription, attrs), | |
| {:ok, user} <- update_user(user, %{subscription: subscription}) do |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| defmodule MyApp.Domain.User.SignUp do | |
| def create_and_subscribe_user(attrs) do | |
| Repo.transaction(fn -> | |
| with {:ok, user} <- create_user(attrs), | |
| {:ok, plans} <- fetch_subscription_plans(attrs), | |
| {:ok, charge} <- charge_card(user, subscription), | |
| {:ok, subscription} <- create_subscription(user, plan, attrs), | |
| {:ok, _delivery} <- schedule_delivery(user, subscription, attrs), | |
| {:ok, _receipt} <- send_email_receipt(user, subscription, attrs), | |
| {:ok, user} <- update_user(user, %{subscription: subscription}) do |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| defmodule BookingApp.Sage do | |
| import Sage | |
| @spec book_trip(attrs :: map()) :: {:ok, last_effect :: any(), all_effects :: map()} | {:error, reason :: any()} | |
| def book_trip(attrs) do | |
| new() | |
| |> run(:exchange_rate, &Billing.fetch_currency_exchange_rates/2, &Billing.currency_exchange_rates_circuit_breaker/4) | |
| |> run(:authorization, &Billing.authorize_card/2, &Billing.cancel_card_authorization/4) | |
| |> run_async(:book_hotel, &HotelsBooking.book/2, &HotelsBooking.cancel_booking/4) | |
| |> run_async(:book_car, &CarsBooking.book/2, &CarsBooking.cancel_booking/4) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| def currency_exchange_rates_circuit_breaker(_effect_to_compensate, _effects_so_far, %{"base_currency" => base_currency}) do | |
| with {:ok, exchange_rates} <- BookingApp.Cache.fetch(:eur_exchange_rates, base_currency) do | |
| {:continue, exchange_rates} | |
| else | |
| _ -> :ok | |
| end | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @callback transaction(attrs :: map()) :: | |
| {:ok, last_effect :: any(), all_effects :: map()} | {:error, reason :: any()} | |
| @callback compensation(effect_to_compensate :: any(), effects_so_far :: map(), attrs :: any()) :: | |
| :ok | |
| | :abort | |
| | {:retry, | |
| [ | |
| {:retry_limit, pos_integer()}, | |
| {:base_backoff, pos_integer() | nil}, |