Last active
May 20, 2018 12:47
-
-
Save AndrewDryga/0a13318d4c4a7dafd0db35bf338dd6bd to your computer and use it in GitHub Desktop.
Sage: Business Logic Getting Worse
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 | |
{:ok, user} | |
else | |
{:error, {:charge_failed, _reason} = error} -> | |
# First problem: charge is not available here | |
:ok = refund(charge) | |
{:error, error} | |
{:error, {:create_subscription, _reason} = error} -> | |
# Second problem: growing list of compensations | |
:ok = refund(charge) | |
:ok = delete_subscription(subscription) | |
{:error, error} | |
# Third problem: how to decide when we should be sending another email or | |
# at which stage we've failed? | |
other -> | |
# Will rollback transaction on all other errors | |
:ok = ensure_deleted(fn -> refund(charge) end) | |
:ok = ensure_deleted(fn -> delete_subscription(subscription) end) | |
:ok = ensure_deleted(fn -> delete_delivery_from_schedule(delivery) end) | |
other | |
end | |
end) | |
end | |
defp ensure_deleted(cb) do | |
case cb.() do | |
:ok -> :ok | |
{:error, :not_found} -> :ok | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment