git.iko.soy/typeable/postgresql-simple
on master help sign in
Merge remote-tracking branch 'ocharles/general-transaction-retrying' into 0.3
commit06df1a125561bb084bd8415f623782c2d74dee0f authorLeon P Smith <leon@melding-monads.com> dateSun 6 Jan 2013, 19:06 (14 years ago) parent2f9bf6fc96a43d
1 file changed+19−13
src/Database/PostgreSQL/Simple.hs+19−13
src/Database/PostgreSQL/Simple.hs+19−13
@@ -667,6 +667,15 @@ withTransactionSerializable =
667667 { isolationLevel = Serializable
668668 , readWriteMode = ReadWrite
669669 }
670+ retryOnNotSerializable
671+ where
672+ retryOnNotSerializable exception =
673+ case exception of
674+ SqlError{..} | sqlState == serialization_failure
675+ -> True
676+ _ -> False
677+ -- http://www.postgresql.org/docs/current/static/errcodes-appendix.html
678+ serialization_failure = "40001"
670679
671680-- | Execute an action inside a SQL transaction with a given isolation level.
672681withTransactionLevel :: IsolationLevel -> Connection -> IO a -> IO a
@@ -682,14 +691,15 @@ withTransactionMode mode conn act =
682691 commit conn
683692 return r
684693
685−-- | Like 'withTransactionMode', but if a 'SqlError' arises whose 'sqlState' is
686−-- @\"40001\"@ (@serialization_failure@), this will issue a @ROLLBACK@, then
687−-- try the action again. If any other exception arises, this will issue a
688−-- @ROLLBACK@, but will propagate the exception instead of retrying.
694+-- | Like 'withTransactionMode', but also takes a custom callback to
695+-- determine if a transaction should be retried if an 'SqlError' occurs.
696+-- If the callback returns True, then the transaction will be retried.
697+-- If the callback returns False, or an exception other than an 'SqlError'
698+-- occurs then the transaction will be rolled back and the exception rethrown.
689699--
690700-- This is used to implement 'withTransactionSerializable'.
691−withTransactionModeRetry :: TransactionMode -> Connection -> IO a -> IO a
692−withTransactionModeRetry mode conn act =
701+withTransactionModeRetry :: TransactionMode -> (SqlError -> Bool) -> Connection -> IO a -> IO a
702+withTransactionModeRetry mode shouldRetry conn act =
693703 mask $ \restore ->
694704 retryLoop $ try $ do
695705 a <- restore act
@@ -703,16 +713,12 @@ withTransactionModeRetry mode conn act =
703713 case r of
704714 Left e -> do
705715 rollback conn
706− case fromException e of
707− Just SqlError{..} | sqlState == serialization_failure
708− -> retryLoop act'
709− _ -> throwIO e
716+ case fmap shouldRetry (fromException e) of
717+ Just True -> retryLoop act'
718+ _ -> throwIO e
710719 Right a ->
711720 return a
712721
713− -- http://www.postgresql.org/docs/current/static/errcodes-appendix.html
714− serialization_failure = "40001"
715−
716722-- | Rollback a transaction.
717723rollback :: Connection -> IO ()
718724rollback conn = execute_ conn "ABORT" >> return ()