Skip to content
Permalink
Browse files

db/webapi: Run all transactions at an isolation level of Serializable

Modify both the 'db' and the 'webapi' versions of 'runQuery' to use
the 'Serializable' isolation level which is the most strict.

Before this change queries returning a 'CAddressSummary' struct would
sometimes return negative balances although this was actually a
consequence of previous database corruption.

See: https://www.postgresql.org/docs/current/transaction-iso.html
  • Loading branch information
erikd committed Dec 3, 2019
1 parent 7e05be2 commit 637f7826f33a63572df8414ae3ad113022286320
@@ -30,7 +30,7 @@ import qualified Data.Text.Lazy.Builder as LT

import Database.Persist.Postgresql (withPostgresqlConn, openSimpleConn)
import Database.PostgreSQL.Simple (connectPostgreSQL)
import Database.Persist.Sql (SqlBackend, runSqlConn)
import Database.Persist.Sql (SqlBackend, IsolationLevel (..), runSqlConnWithIsolation)

import Database.Esqueleto
import Database.Esqueleto.Internal.Sql
@@ -49,9 +49,9 @@ runDbHandleLogger logHandle dbAction = do
pgconf <- readPGPassFileEnv
runHandleLoggerT .
withPostgresqlConn (toConnectionString pgconf) $ \backend ->
-- The 'runSqlConn' function starts a transaction, runs the 'dbAction'
-- The 'runSqlConnWithIsolation' function starts a transaction, runs the 'dbAction'
-- and then commits the transaction.
runSqlConn dbAction backend
runSqlConnWithIsolation dbAction backend Serializable
where
runHandleLoggerT :: LoggingT m a -> m a
runHandleLoggerT action =
@@ -68,7 +68,7 @@ runDbIohkLogging tracer dbAction = do
pgconf <- readPGPassFileEnv
(runIohkLogging tracer) .
withPostgresqlConn (toConnectionString pgconf) $ \backend ->
runSqlConn dbAction backend
runSqlConnWithIsolation dbAction backend Serializable

runIohkLogging :: Trace IO Text -> LoggingT m a -> m a
runIohkLogging tracer action =
@@ -96,15 +96,15 @@ runDbNoLogging action = do
pgconfig <- readPGPassFileEnv
runNoLoggingT .
withPostgresqlConn (toConnectionString pgconfig) $ \backend ->
runSqlConn action backend
runSqlConnWithIsolation action backend Serializable

-- | Run a DB action with stdout logging. Mainly for debugging.
runDbStdoutLogging :: ReaderT SqlBackend (LoggingT IO) b -> IO b
runDbStdoutLogging action = do
pgconfig <- readPGPassFileEnv
runStdoutLoggingT .
withPostgresqlConn (toConnectionString pgconfig) $ \backend ->
runSqlConn action backend
runSqlConnWithIsolation action backend Serializable

-- from Control.Monad.Logger, wasnt exported
defaultOutput :: Handle
@@ -37,7 +37,7 @@ import Data.Time.Clock (UTCTime)
import Data.Time.Clock.POSIX (POSIXTime, utcTimeToPOSIXSeconds)
import Data.Word (Word16, Word64)

import Database.Persist.Sql (SqlBackend, runSqlConn)
import Database.Persist.Sql (IsolationLevel (..), SqlBackend, runSqlConnWithIsolation)

import Explorer.DB (Block (..), TxId)

@@ -86,7 +86,7 @@ k = 2160

runQuery :: MonadIO m => SqlBackend -> ReaderT SqlBackend IO a -> m a
runQuery backend query =
liftIO $ runSqlConn query backend
liftIO $ runSqlConnWithIsolation query backend Serializable

slotsPerEpoch :: Word64
slotsPerEpoch = k * 10

0 comments on commit 637f782

Please sign in to comment.
You can’t perform that action at this time.