Skip to content

Commit

Permalink
widen 'isMigrationError' to catch constraint errors
Browse files Browse the repository at this point in the history
On start-up, we run persistent migrations and in case of migration issues, we
execute some particular handling (e.g. the pool db resets itself). Yet, we
failed at catching migration issues coming from constraints introduced later
and that can't be satisfied on already existing data. This commit fixes it.

Before
======

[cardano-wallet.network:Info:22] Jörmungandr is ready.
cardano-wallet-jormungandr: SQLite3 returned ErrorConstraint while attempting to perform step: NOT NULL constraint failed: pool_owner_backup.pool_owner_index
(exiting with an error code)

After
=====

[cardano-wallet.network:Info:22] Jörmungandr is ready.
[cardano-wallet.stake-pool-db:Error:22]  Failed to migrate the database: : NOT NULL constraint failed: pool_owner_backup.pool_owner_index
[cardano-wallet.stake-pool-db:Notice:22] Non backward compatible database found. Removing old database and re-creating it from scratch. Ignore the previous error.
[cardano-wallet.stake-pool-db:Notice:22] 1 migrations were applied to the database.
(... and continuing as normal)
  • Loading branch information
KtorZ committed Jan 13, 2020
1 parent e902913 commit c68cc47
Showing 1 changed file with 23 additions and 10 deletions.
33 changes: 23 additions & 10 deletions lib/core/src/Cardano/DB/Sqlite.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
{-# LANGUAGE OverloadedLabels #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}

Expand Down Expand Up @@ -55,6 +56,8 @@ import Control.Tracer
( Tracer, traceWith )
import Data.Aeson
( ToJSON )
import Data.Function
( (&) )
import Data.List
( isInfixOf )
import Data.List.Split
Expand Down Expand Up @@ -185,8 +188,9 @@ startSqliteBackend migrateAll trace fp = do
observe = bracket_ (traceRun False) (traceRun True)
let runQuery :: SqlPersistT IO a -> IO a
runQuery cmd = withMVar lock $ const $ observe $ runSqlConn cmd backend
migrations <- tryJust isMigrationError $ runQuery $
runMigrationQuiet migrateAll
migrations <- runQuery (runMigrationQuiet migrateAll)
& tryJust (isMigrationError @PersistException)
& tryJust (isMigrationError @SqliteException)
traceWith trace $ MsgMigrations (fmap length migrations)
let ctx = SqliteContext backend runQuery fp trace
case migrations of
Expand All @@ -195,14 +199,23 @@ startSqliteBackend migrateAll trace fp = do
pure $ Left e
Right _ -> pure $ Right ctx

-- | Exception predicate for migration errors.
isMigrationError :: PersistException -> Maybe MigrationError
isMigrationError e
| mark `isInfixOf` msg = Just $ MigrationError $ T.pack msg
| otherwise = Nothing
where
msg = show e
mark = "Database migration: manual intervention required."
class Exception e => IsMigrationError e where
-- | Exception predicate for migration errors.
isMigrationError :: e -> Maybe MigrationError

instance IsMigrationError PersistException where
isMigrationError e
| mark `isInfixOf` msg = Just $ MigrationError $ T.pack msg
| otherwise = Nothing
where
msg = show e
mark = "Database migration: manual intervention required."

instance IsMigrationError SqliteException where
isMigrationError (SqliteException ErrorConstraint _ msg) =
Just $ MigrationError msg
isMigrationError _ =
Nothing

createSqliteBackend
:: Tracer IO DBLog
Expand Down

0 comments on commit c68cc47

Please sign in to comment.