module Tendermint.SDK.BaseApp.Effects.BaseEffs
  ( BaseEffs
  , evalBaseEffs
  , evalBaseEffsPure
  ) where

import           Control.Exception                         (throwIO)
import           Control.Monad.IO.Class                    (liftIO)
import           Polysemy                                  (Embed, Members, Sem)
import           Polysemy.Error                            (Error, runError)
import           Polysemy.Reader                           (Reader)
import           Polysemy.Resource                         (Resource,
                                                            resourceToIO)
import           Tendermint.SDK.BaseApp.Errors             (AppError)
import           Tendermint.SDK.BaseApp.Logger             (Logger)
import qualified Tendermint.SDK.BaseApp.Logger.Katip       as KL
import           Tendermint.SDK.BaseApp.Metrics            (Metrics)
import qualified Tendermint.SDK.BaseApp.Metrics.Prometheus as Prometheus
import           Tendermint.SDK.Types.Effects              ((:&))

-- | Concrete row of effects for the BaseApp. Note that because there does
-- | not exist an interpreter for an untagged 'RawStore', you must scope
-- | these effects before they can be interpreted.
type BaseEffs =
  [ Metrics
  , Logger
  , Resource
  , Error AppError
  ]

-- | An intermediary interpeter, bringing 'BaseApp' down to 'CoreEff'.
evalBaseEffs
  :: Members [Embed IO, Reader KL.LogConfig, Reader (Maybe Prometheus.PrometheusEnv)] core
  => forall a.
     Sem (BaseEffs :& core) a
  -> Sem core a
evalBaseEffs :: forall a. Sem (BaseEffs :& core) a -> Sem core a
evalBaseEffs action :: Sem (BaseEffs :& core) a
action = do
  Either AppError a
eRes <- Sem (Error AppError : core) a -> Sem core (Either AppError a)
forall e (r :: [(* -> *) -> * -> *]) a.
Sem (Error e : r) a -> Sem r (Either e a)
runError (Sem (Error AppError : core) a -> Sem core (Either AppError a))
-> (Sem (Metrics : Logger : Resource : Error AppError : core) a
    -> Sem (Error AppError : core) a)
-> Sem (Metrics : Logger : Resource : Error AppError : core) a
-> Sem core (Either AppError a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
    Sem (Resource : Error AppError : core) a
-> Sem (Error AppError : core) a
forall (r :: [(* -> *) -> * -> *]) a.
Member (Embed IO) r =>
Sem (Resource : r) a -> Sem r a
resourceToIO (Sem (Resource : Error AppError : core) a
 -> Sem (Error AppError : core) a)
-> (Sem (Metrics : Logger : Resource : Error AppError : core) a
    -> Sem (Resource : Error AppError : core) a)
-> Sem (Metrics : Logger : Resource : Error AppError : core) a
-> Sem (Error AppError : core) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
    Sem (Logger : Resource : Error AppError : core) a
-> Sem (Resource : Error AppError : core) a
forall (r :: [(* -> *) -> * -> *]) a.
KatipContext (Sem r) =>
Sem (Logger : r) a -> Sem r a
KL.evalKatip (Sem (Logger : Resource : Error AppError : core) a
 -> Sem (Resource : Error AppError : core) a)
-> (Sem (Metrics : Logger : Resource : Error AppError : core) a
    -> Sem (Logger : Resource : Error AppError : core) a)
-> Sem (Metrics : Logger : Resource : Error AppError : core) a
-> Sem (Resource : Error AppError : core) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
    Sem (Metrics : Logger : Resource : Error AppError : core) a
-> Sem (Logger : Resource : Error AppError : core) a
forall (r :: [(* -> *) -> * -> *]) a.
(Member (Embed IO) r, Member (Reader (Maybe PrometheusEnv)) r) =>
Sem (Metrics : r) a -> Sem r a
Prometheus.evalWithMetrics (Sem (Metrics : Logger : Resource : Error AppError : core) a
 -> Sem core (Either AppError a))
-> Sem (Metrics : Logger : Resource : Error AppError : core) a
-> Sem core (Either AppError a)
forall a b. (a -> b) -> a -> b
$
    Sem (Metrics : Logger : Resource : Error AppError : core) a
Sem (BaseEffs :& core) a
action
  (AppError -> Sem core a)
-> (a -> Sem core a) -> Either AppError a -> Sem core a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (IO a -> Sem core a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a -> Sem core a)
-> (AppError -> IO a) -> AppError -> Sem core a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AppError -> IO a
forall e a. Exception e => e -> IO a
throwIO) a -> Sem core a
forall (m :: * -> *) a. Monad m => a -> m a
return Either AppError a
eRes

evalBaseEffsPure
  :: Members [Embed IO, Reader KL.LogConfig] core
  => forall a.
     Sem (BaseEffs :& core) a
  -> Sem core a
evalBaseEffsPure :: forall a. Sem (BaseEffs :& core) a -> Sem core a
evalBaseEffsPure action :: Sem (BaseEffs :& core) a
action = do
  Either AppError a
eRes <- Sem (Error AppError : core) a -> Sem core (Either AppError a)
forall e (r :: [(* -> *) -> * -> *]) a.
Sem (Error e : r) a -> Sem r (Either e a)
runError (Sem (Error AppError : core) a -> Sem core (Either AppError a))
-> (Sem (Metrics : Logger : Resource : Error AppError : core) a
    -> Sem (Error AppError : core) a)
-> Sem (Metrics : Logger : Resource : Error AppError : core) a
-> Sem core (Either AppError a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
    Sem (Resource : Error AppError : core) a
-> Sem (Error AppError : core) a
forall (r :: [(* -> *) -> * -> *]) a.
Member (Embed IO) r =>
Sem (Resource : r) a -> Sem r a
resourceToIO (Sem (Resource : Error AppError : core) a
 -> Sem (Error AppError : core) a)
-> (Sem (Metrics : Logger : Resource : Error AppError : core) a
    -> Sem (Resource : Error AppError : core) a)
-> Sem (Metrics : Logger : Resource : Error AppError : core) a
-> Sem (Error AppError : core) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
    Sem (Logger : Resource : Error AppError : core) a
-> Sem (Resource : Error AppError : core) a
forall (r :: [(* -> *) -> * -> *]) a.
KatipContext (Sem r) =>
Sem (Logger : r) a -> Sem r a
KL.evalKatip (Sem (Logger : Resource : Error AppError : core) a
 -> Sem (Resource : Error AppError : core) a)
-> (Sem (Metrics : Logger : Resource : Error AppError : core) a
    -> Sem (Logger : Resource : Error AppError : core) a)
-> Sem (Metrics : Logger : Resource : Error AppError : core) a
-> Sem (Resource : Error AppError : core) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
    Sem (Metrics : Logger : Resource : Error AppError : core) a
-> Sem (Logger : Resource : Error AppError : core) a
forall (r :: [(* -> *) -> * -> *]) a.
Sem (Metrics : r) a -> Sem r a
Prometheus.evalNothing (Sem (Metrics : Logger : Resource : Error AppError : core) a
 -> Sem core (Either AppError a))
-> Sem (Metrics : Logger : Resource : Error AppError : core) a
-> Sem core (Either AppError a)
forall a b. (a -> b) -> a -> b
$
    Sem (Metrics : Logger : Resource : Error AppError : core) a
Sem (BaseEffs :& core) a
action
  (AppError -> Sem core a)
-> (a -> Sem core a) -> Either AppError a -> Sem core a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (IO a -> Sem core a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a -> Sem core a)
-> (AppError -> IO a) -> AppError -> Sem core a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AppError -> IO a
forall e a. Exception e => e -> IO a
throwIO) a -> Sem core a
forall (m :: * -> *) a. Monad m => a -> m a
return Either AppError a
eRes