postgresql-tx 0.2.0.0 → 0.3.0.0
raw patch · 5 files changed
+48/−29 lines, 5 files
Files
- CHANGELOG.md +4/−0
- package.yaml +1/−1
- postgresql-tx.cabal +2/−2
- src/Database/PostgreSQL/Tx.hs +0/−1
- src/Database/PostgreSQL/Tx/Internal.hs +41/−25
CHANGELOG.md view
@@ -1,5 +1,9 @@ # Change log +## 0.3.0.0++* Removed `TxErrorType` and change the `errorType` field on `TxException` to `errcode`.+ ## 0.2.0.0 * Changed the `TxM` encoding from a plain newtype-over-IO to a reader.
package.yaml view
@@ -1,5 +1,5 @@ name: postgresql-tx-version: 0.2.0.0+version: 0.3.0.0 github: "simspace/postgresql-tx" license: BSD3 license-file: LICENSE.md
postgresql-tx.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 6502ef6d385db187552d31216c423233d2ea504b31a19ce4f273aa8aeb6773c0+-- hash: 66842eb2c8ecef116494783907dbe032bf945a4e2439098e2d7a5f5da57296da name: postgresql-tx-version: 0.2.0.0+version: 0.3.0.0 synopsis: A safe transaction monad for use with various PostgreSQL Haskell libraries. description: Please see the README on GitHub at <https://github.com/simspace/postgresql-tx#readme> category: Database
src/Database/PostgreSQL/Tx.hs view
@@ -15,7 +15,6 @@ , throwExceptionTx , mapExceptionTx , TxException(..)- , TxErrorType(..) , shouldRetryTx ) where
src/Database/PostgreSQL/Tx/Internal.hs view
@@ -9,6 +9,7 @@ {-# LANGUAGE KindSignatures #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE TypeFamilies #-}@@ -160,43 +161,58 @@ Nothing -> throwIO ex Just ex' -> throwIO ex' +-- | Unified exception type thrown from the database.+--+-- Each database backend may throw different types of exceptions.+-- As a user of @postgresql-tx@, ideally we should be able to+-- detect exceptions from the database without needing to catch+-- the database backend's exception type.+--+-- The 'errcode' field allows us to introspect the postgresql+-- @errcode@; see https://www.postgresql.org/docs/current/errcodes-appendix.html+--+-- If you need to inspect the exact exception thrown by a database+-- backend, use the 'cause' field. data TxException = TxException- { errorType :: TxErrorType+ { errcode :: Maybe String , cause :: SomeException } deriving stock (Show) instance Exception TxException -data TxErrorType =- TxSerializationFailure- | TxDeadlockDetected- | TxOtherError (Maybe String) -- ^ PostgreSQL @errcode@, if applicable.- deriving stock (Show, Eq)+-- | PostgreSQL @errcode@ for @serialization_failure@.+errcode'serialization_failure :: String+errcode'serialization_failure = "40001" -shouldRetryTx :: TxException -> Bool-shouldRetryTx e =- errorType e `elem`- [ TxSerializationFailure- , TxDeadlockDetected- ]+-- | PostgreSQL @errcode@ for @deadlock_detected@.+errcode'deadlock_detected :: String+errcode'deadlock_detected = "40P01" -fromSqlState :: Maybe String -> TxErrorType-fromSqlState = \case- Just "40001" -> TxSerializationFailure- Just "40P01" -> TxDeadlockDetected- sqlState -> TxOtherError sqlState+-- | Checks if the 'errcode' of a 'TxException' matches the supplied predicate.+-- If the 'errcode' is 'Nothing', returns 'False'.+hasErrcode :: (String -> Bool) -> TxException -> Bool+hasErrcode p TxException { errcode } = any p errcode +-- | Useful as a predicate to indicate when to retry transactions which are+-- run at isolation level @serializable@+shouldRetryTx :: TxException -> Bool+shouldRetryTx =+ hasErrcode+ (`elem`+ [ errcode'serialization_failure+ , errcode'deadlock_detected+ ])++-- | Construct a 'TxException' from an @errcode@ accessing function+-- and the 'cause' exception.+--+-- Note that this function should only be used by libraries+-- which are implementing a database backend for @postgresql-tx@. unsafeMkTxException :: (Exception e) => (e -> Maybe String) -> e -> TxException-unsafeMkTxException f = unsafeMkTxException' (fromSqlState . f)--unsafeMkTxException'- :: (Exception e)- => (e -> TxErrorType)- -> e -> TxException-unsafeMkTxException' f e =+unsafeMkTxException f e = TxException- { errorType = f e+ { errcode = f e , cause = toException e }