orville-postgresql-1.0.0.0: src/Orville/PostgreSQL/Monad/Orville.hs
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{- |
Copyright : Flipstone Technology Partners 2023
License : MIT
Stability : Stable
@since 1.0.0.0
-}
module Orville.PostgreSQL.Monad.Orville
( Orville
, runOrville
, runOrvilleWithState
)
where
import qualified Control.Exception.Safe as ExSafe
import Control.Monad.IO.Class (MonadIO)
import Control.Monad.Trans.Reader (ReaderT, runReaderT)
import qualified Orville.PostgreSQL.ErrorDetailLevel as ErrorDetailLevel
import qualified Orville.PostgreSQL.Monad.HasOrvilleState as HasOrvilleState
import qualified Orville.PostgreSQL.Monad.MonadOrville as MonadOrville
import qualified Orville.PostgreSQL.OrvilleState as OrvilleState
import Orville.PostgreSQL.Raw.Connection (ConnectionPool)
{- |
The 'Orville' Monad provides an easy starter implementation of
'MonadOrville.MonadOrville' when you don't have a monad specific to your
application that you need to use.
If you want to add Orville capabilities to your own monad, take a look at
'MonadOrville.MonadOrville' to learn what needs to be done.
@since 1.0.0.0
-}
newtype Orville a = Orville
{ unwrapOrville :: ReaderT OrvilleState.OrvilleState IO a
}
deriving
( Functor
, Applicative
, Monad
, MonadIO
, MonadOrville.MonadOrvilleControl
, MonadOrville.MonadOrville
, HasOrvilleState.HasOrvilleState
, ExSafe.MonadThrow
, ExSafe.MonadCatch
)
{- |
Runs an 'Orville' operation in the 'IO' monad using the given connection
pool.
This will run the 'Orville' operation with the
'ErrorDetailLevel.ErrorDetailLevel' set to the default. If you want to run
with a different detail level, you can use 'OrvilleState.newOrvilleState' to
create a state with the desired detail level and then use
'runOrvilleWithState'.
@since 1.0.0.0
-}
runOrville :: ConnectionPool -> Orville a -> IO a
runOrville =
runOrvilleWithState
. OrvilleState.newOrvilleState ErrorDetailLevel.defaultErrorDetailLevel
{- |
Runs an 'Orville' operation in the 'IO' monad, starting from the provided
'OrvilleState.OrvilleState'.
Caution: If you harvest an 'OrvilleState.OrvilleState' from inside a
'MonadOrville.MonadOrville' monad using 'MonadOrville.askOrvilleState',
you may pick up connection tracking state that you didn't intend to. You
may want to use 'MonadOrville.resetOrvilleState' in this situation to get
a new initial state before passing it to 'runOrvilleWithState'.
On the other hand, if you know that you want to pass the existing connection
state from another monad into the 'Orville' monad, this is how you do it.
@since 1.0.0.0
-}
runOrvilleWithState :: OrvilleState.OrvilleState -> Orville a -> IO a
runOrvilleWithState state orville =
runReaderT (unwrapOrville orville) state