在RunDb中的MaybeT和Transactions

时间:2015-07-09 07:24:42

标签: haskell persistent

对于我之前关于链接失败的问题,Michael Snoyman建议我使用MaybeT来运行它们,这样如果其中任何一个失败,它就会短路到Nothing

我的印象是runDb在交易中运行所有内容。那么代码中的任何一点都不能自动回滚事务吗?

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

当我运行上面的代码时,getBy失败但用户仍然插入。我错误地认为runDb会在Nothing MaybeT内回滚吗?我是否需要使用其他Monad才能使用?

感谢您对如何最好地回滚失败的想法。

更新: 根据迈克尔的建议,这就是我最终做的事情。

mauth <- runDb $ do
          ma <- runMaybeT $ do
                   valid <- ... 
          case ma of
            Just _ -> return ma
            Nothing -> liftIO $ throwIO MyException

现在我需要弄清楚如何在外部很好地捕获此异常并返回正确的错误消息。

谢谢!

1 个答案:

答案 0 :(得分:3)

返回Nothing与失败并非同一回事。你需要为Persistent抛出一个运行时异常(通过throwIO之类的东西)来将其视为回滚情况。