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 6b3e817 commit 98dadd1090597416ef23fe1c3b88419ba060dc94
@@ -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 98dadd1

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