Skip to content

Commit

Permalink
db-sync: Handle rool back of PoolMetadataRef before result inserted
Browse files Browse the repository at this point in the history
If a rollback occurs after the PoolMetadataRef is fetched, the
insertion of the result can fail. In this insert fail case, we simply log
and drop the exception.

Closes: #806
  • Loading branch information
erikd committed Sep 12, 2021
1 parent a206f9b commit 36c96bc
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 9 deletions.
2 changes: 2 additions & 0 deletions cardano-db-sync/cardano-db-sync.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ library
, cardano-slotting
, containers
, esqueleto
, exceptions
, extra
, groups
, http-client
Expand All @@ -118,6 +119,7 @@ library
, ouroboros-network
, persistent
, persistent-postgresql
, postgresql-simple
, prometheus
, random-shuffle
, small-steps
Expand Down
3 changes: 2 additions & 1 deletion cardano-db-sync/src/Cardano/DbSync/Era/Shelley/Insert.hs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import Cardano.Ledger.Mary.Value (AssetName (..), PolicyID (..), Value
import Cardano.Slotting.Block (BlockNo (..))
import Cardano.Slotting.Slot (EpochNo (..), EpochSize (..), SlotNo (..))

import Control.Monad.Catch (MonadCatch)
import Control.Monad.Class.MonadSTM.Strict (tryReadTBQueue)
import Control.Monad.Trans.Control (MonadBaseControl)

Expand All @@ -76,7 +77,7 @@ import qualified Shelley.Spec.Ledger.STS.Chain as Shelley
import qualified Shelley.Spec.Ledger.TxBody as Shelley

insertShelleyBlock
:: (MonadBaseControl IO m, MonadIO m)
:: (MonadBaseControl IO m, MonadCatch m, MonadIO m)
=> Trace IO Text -> LedgerEnv -> Generic.Block -> LedgerStateSnapshot -> SlotDetails
-> ReaderT SqlBackend m (Either SyncNodeError ())
insertShelleyBlock tracer lenv blk lStateSnap details = do
Expand Down
21 changes: 14 additions & 7 deletions cardano-db-sync/src/Cardano/DbSync/Era/Shelley/Offline.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,17 @@ module Cardano.DbSync.Era.Shelley.Offline
, runOfflineFetchThread
) where

import Cardano.Prelude
import Cardano.Prelude hiding (handle)

import Cardano.BM.Trace (Trace, logInfo)
import Cardano.BM.Trace (Trace, logInfo, logWarning)

import Cardano.DbSync.Era.Shelley.Offline.Http
import Cardano.DbSync.Era.Shelley.Offline.Query
import Cardano.DbSync.Era.Shelley.Offline.Types

import Cardano.Sync.Types

import Control.Monad.Catch (MonadCatch, handle)
import Control.Monad.Class.MonadSTM.Strict (TBQueue, flushTBQueue, isEmptyTBQueue,
readTBQueue, writeTBQueue)
import Control.Monad.Trans.Control (MonadBaseControl)
Expand All @@ -43,6 +44,7 @@ import Cardano.Sync.LedgerState
import Cardano.Sync.Util

import Database.Persist.Sql (SqlBackend)
import Database.PostgreSQL.Simple (SqlError)

import Network.HTTP.Client (HttpException (..))
import qualified Network.HTTP.Client as Http
Expand All @@ -68,7 +70,7 @@ loadOfflineWorkQueue _trce workQueue =
queueInsert = atomically . writeTBQueue workQueue

insertOfflineResults
:: (MonadBaseControl IO m, MonadIO m)
:: (MonadBaseControl IO m, MonadCatch m, MonadIO m)
=> Trace IO Text -> TBQueue IO FetchResult -> ReaderT SqlBackend m ()
insertOfflineResults trce resultQueue = do
res <- liftIO . atomically $ flushTBQueue resultQueue
Expand All @@ -80,18 +82,23 @@ insertOfflineResults trce resultQueue = do
]
mapM_ insert res
where
insert :: (MonadBaseControl IO m, MonadIO m) => FetchResult -> ReaderT SqlBackend m ()
insert :: (MonadBaseControl IO m, MonadCatch m, MonadIO m) => FetchResult -> ReaderT SqlBackend m ()
insert fr =
case fr of
ResultMetadata md -> void $ DB.insertPoolOfflineData md
ResultError fe -> void $ DB.insertPoolOfflineFetchError fe
-- If a rollback occurs after the PoolMetadataRef is fetched, the insertion of the
-- result can fail. In this insert fail case, we simply log and drop the exception.
handle (liftIO . logFail) $
case fr of
ResultMetadata md -> void $ DB.insertPoolOfflineData md
ResultError fe -> void $ DB.insertPoolOfflineFetchError fe

isFetchError :: FetchResult -> Bool
isFetchError fe =
case fe of
ResultMetadata {} -> False
ResultError {} -> True

logFail :: SqlError -> IO ()
logFail e = logWarning trce $ "insertOfflineResults: " <> textShow e

runOfflineFetchThread :: Trace IO Text -> LedgerEnv -> IO ()
runOfflineFetchThread trce lenv = do
Expand Down
3 changes: 2 additions & 1 deletion cardano-db-sync/src/Cardano/DbSync/Plugin/Default.hs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import Cardano.Sync.Plugin
import Cardano.Sync.Types
import Cardano.Sync.Util

import Control.Monad.Catch (MonadCatch)
import Control.Monad.Class.MonadSTM.Strict (putTMVar, tryTakeTMVar)
import Control.Monad.Trans.Control (MonadBaseControl)
import Control.Monad.Trans.Except.Extra (newExceptT)
Expand Down Expand Up @@ -73,7 +74,7 @@ insertDefaultBlock backend tracer env blockDetails = do
runExceptT (traverse_ insert blockDetails)
where
insert
:: (MonadBaseControl IO m, MonadIO m)
:: (MonadBaseControl IO m, MonadCatch m, MonadIO m)
=> BlockDetails -> ExceptT SyncNodeError (ReaderT SqlBackend m) ()
insert (BlockDetails cblk details) = do
-- Calculate the new ledger state to pass to the DB insert functions but do not yet
Expand Down

0 comments on commit 36c96bc

Please sign in to comment.