fradrive/src/Utils/Sql.hs
2018-10-31 23:55:29 +01:00

33 lines
980 B
Haskell

module Utils.Sql
( setSerializable
) where
import ClassyPrelude.Yesod
import Database.Persist.Sql
import Database.PostgreSQL.Simple (SqlError(SqlError), sqlErrorHint)
import Control.Monad.Catch (handleIf)
import Data.Time.Clock
setSerializable :: (MonadLogger m, MonadCatch m, MonadBase IO m, MonadIO m) => ReaderT SqlBackend m a -> ReaderT SqlBackend m a
setSerializable act = setSerializable' (0 :: Integer)
where
act' = [executeQQ|SET TRANSACTION ISOLATION LEVEL SERIALIZABLE|] *> act
setSerializable' (min 10 -> logBackoff) =
handleIf
(\SqlError{sqlErrorHint} -> "The transaction might succeed if retried." `isInfixOf` sqlErrorHint)
(\e -> do
let
delay :: NominalDiffTime
delay = 1e-3 * 2 ^ logBackoff
$logWarnS "Sql" $ tshow (delay, e)
transactionUndo
threadDelay . round $ delay * 1e6
setSerializable' (succ logBackoff)
)
act'