问题
For my previous question on chaining failures, Michael Snoyman had suggested I use MaybeT to run them so if any of them fails, it will just short-circuit to Nothing.
I was under the impression runDb runs everything in a transaction. So shouldn't a failure at any point in code automatically rollback the transaction?
mauth <- runDb $ runMaybeT $ do
valid <- MaybeT $ return $ listToMaybe errs
uid <- MaybeT $ insertUnique u
vid <- MaybeT $ getBy $ UniqueField v -- this step fails but previous insert does not roll back
auth <- liftIO $ createAuthToken uid
return auth
When I run the above code, the getBy fails but user was still inserted. Am I misunderstanding that runDb will rollback on a Nothing inside MaybeT? Do I need to use some other Monad for this to work?
Appreciate your thoughts on how to best rollback on failure.
Update: This is what I ended up doing per Michael's suggestion.
mauth <- runDb $ do
ma <- runMaybeT $ do
valid <- ...
case ma of
Just _ -> return ma
Nothing -> liftIO $ throwIO MyException
Now I need to figure out how to catch this exception nicely outside and return a proper error message back.
Thanks!
回答1:
Returning Nothing is not the same thing as a failure. You'd need to throw a runtime exception (via something like throwIO) for Persistent to treat it as a rollback situation.
来源:https://stackoverflow.com/questions/31310736/maybet-and-transactions-in-rundb