Suppose you use a transaction to process a Stripe payment and update a user entity:
@ndb.transactional
def process_payment(user_key, amount):
user = user_key.get()
user.stripe_payment(amount) # API call to Stripe
user.balance += amount
user.put()
It is possible that the Stripe API call succeeds but that the put
fails because of contention. The user would then be charged, but his account wouldn't reflect the payment.
You could pull the Stripe API call out of the transaction and do the transaction afterwards, but it seems like you still have the same problem. The charge succeeds but the transaction fails and the user's account isn't credited.
This seems like a really common scenario. How does one properly handle this?