module Hasql.Transaction.Private.Sessions
where
import Hasql.Transaction.Private.Prelude
import Hasql.Transaction.Private.Model
import Hasql.Session
import qualified Hasql.Transaction.Private.Statements as Statements
inRetryingTransaction :: IsolationLevel -> Mode -> Session (a, Bool) -> Session a
inRetryingTransaction level mode session =
fix $ \ retry -> do
attemptRes <- tryTransaction level mode session
case attemptRes of
Just a -> return a
Nothing -> retry
tryTransaction :: IsolationLevel -> Mode -> Session (a, Bool) -> Session (Maybe a)
tryTransaction level mode body = do
statement () (Statements.beginTransaction level mode)
bodyRes <- catchError (fmap Just body) $ \ error -> do
statement () Statements.abortTransaction
handleTransactionError error $ return Nothing
case bodyRes of
Just (res, commit) -> catchError (commitOrAbort commit $> Just res) $ \ error -> do
handleTransactionError error $ return Nothing
Nothing -> return Nothing
commitOrAbort commit = if commit
then statement () Statements.commitTransaction
else statement () Statements.abortTransaction
handleTransactionError error onTransactionError = case error of
QueryError _ _ (ResultError (ServerError "40001" _ _ _)) -> onTransactionError
error -> throwError error