mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-18 13:02:11 +03:00
64 lines
1.7 KiB
Haskell
64 lines
1.7 KiB
Haskell
|
{-# OPTIONS -Wno-redundant-constraints #-}
|
||
|
{-# LANGUAGE DeriveAnyClass #-}
|
||
|
|
||
|
-- | A replacement for "Control.Exception" with a few extra helpers.
|
||
|
module Harness.Exceptions
|
||
|
( catchRethrow,
|
||
|
tryInOrder,
|
||
|
module Control.Exception.Safe,
|
||
|
Exceptions (..),
|
||
|
)
|
||
|
where
|
||
|
|
||
|
import Control.Exception.Safe
|
||
|
import Data.String
|
||
|
import GHC.Stack
|
||
|
import Hasura.Prelude hiding (first)
|
||
|
|
||
|
-- | Runs an action with a handler.
|
||
|
--
|
||
|
-- Will run the action. If the action fails and throws an exception,
|
||
|
-- it will run the cleanup and will throw the original exception after it is done.
|
||
|
-- If the cleanup fails as well, it will throw both raised exceptions.
|
||
|
catchRethrow :: HasCallStack => IO a -> IO a -> IO a
|
||
|
catchRethrow action cleanup =
|
||
|
catch
|
||
|
-- attempt action
|
||
|
action
|
||
|
( \actionEx -> do
|
||
|
-- try to cleanup the action
|
||
|
-- if clean also fails, throw both errors
|
||
|
_ <- catch cleanup (throwIO . Exceptions actionEx)
|
||
|
-- if clean succeeds, throw the original error
|
||
|
throwIO actionEx
|
||
|
)
|
||
|
|
||
|
-- | Try actions in order. If one succeeds, it succeeds. If both fail, throw both exceptions.
|
||
|
tryInOrder :: HasCallStack => IO a -> IO a -> IO a
|
||
|
tryInOrder action1 action2 =
|
||
|
catch
|
||
|
action1
|
||
|
( \action1Ex ->
|
||
|
catch
|
||
|
action2
|
||
|
(throwIO . Exceptions action1Ex)
|
||
|
)
|
||
|
|
||
|
-- | Two exceptions, bundled as one.
|
||
|
data Exceptions
|
||
|
= Exceptions SomeException SomeException
|
||
|
deriving anyclass (Exception)
|
||
|
|
||
|
instance Show Exceptions where
|
||
|
show (Exceptions e1 e2) =
|
||
|
unlines
|
||
|
[ "1. " <> indentShow e1,
|
||
|
"2. " <> indentShow e2
|
||
|
]
|
||
|
where
|
||
|
indentShow e =
|
||
|
case lines (show e) of
|
||
|
[] -> ""
|
||
|
first : rest ->
|
||
|
unlines $ first : map (" " <>) rest
|