{-# LANGUAGE FlexibleContexts #-}
module AWS.Lambda.Runtime.Value (
pureRuntime,
pureRuntimeWithContext,
fallibleRuntime,
fallibleRuntimeWithContext,
ioRuntime,
ioRuntimeWithContext,
readerTRuntime,
mRuntimeWithContext
) where
import AWS.Lambda.RuntimeClient (RuntimeClientConfig, getRuntimeClientConfig,
getNextData, sendEventError, sendEventSuccess)
import AWS.Lambda.Combinators (withIOInterface,
withFallibleInterface,
withPureInterface,
withoutContext)
import AWS.Lambda.Context (LambdaContext(..), HasLambdaContext(..), runReaderTLambdaContext)
import Control.Exception (SomeException, displayException)
import Control.Monad (forever)
import Control.Monad.Catch (MonadCatch, try)
import Control.Monad.IO.Class (MonadIO, liftIO)
import Control.Monad.Reader (MonadReader, ReaderT, local)
import Data.Aeson (ToJSON, Value)
import Data.Bifunctor (first)
import Data.Text (unpack)
import System.Environment (setEnv)
runtimeLoop :: (HasLambdaContext r, MonadReader r m, MonadCatch m, MonadIO m, ToJSON result) => RuntimeClientConfig ->
(Value -> m result) -> m ()
runtimeLoop :: RuntimeClientConfig -> (Value -> m result) -> m ()
runtimeLoop RuntimeClientConfig
runtimeClientConfig Value -> m result
fn = do
(ByteString
reqIdBS, Value
event, Either String LambdaContext
eCtx) <- IO (ByteString, Value, Either String LambdaContext)
-> m (ByteString, Value, Either String LambdaContext)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (ByteString, Value, Either String LambdaContext)
-> m (ByteString, Value, Either String LambdaContext))
-> IO (ByteString, Value, Either String LambdaContext)
-> m (ByteString, Value, Either String LambdaContext)
forall a b. (a -> b) -> a -> b
$ RuntimeClientConfig
-> IO (ByteString, Value, Either String LambdaContext)
getNextData RuntimeClientConfig
runtimeClientConfig
Either String result
result <- case Either String LambdaContext
eCtx of
Left String
e -> Either String result -> m (Either String result)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String result -> m (Either String result))
-> Either String result -> m (Either String result)
forall a b. (a -> b) -> a -> b
$ String -> Either String result
forall a b. a -> Either a b
Left String
e
Right LambdaContext
ctx ->
(r -> r) -> m (Either String result) -> m (Either String result)
forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
local (LambdaContext -> r -> r
forall r. HasLambdaContext r => LambdaContext -> r -> r
withContext LambdaContext
ctx) (m (Either String result) -> m (Either String result))
-> m (Either String result) -> m (Either String result)
forall a b. (a -> b) -> a -> b
$ do
IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ String -> String -> IO ()
setEnv String
"_X_AMZN_TRACE_ID" (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Text -> String
unpack (Text -> String) -> Text -> String
forall a b. (a -> b) -> a -> b
$ LambdaContext -> Text
xRayTraceId LambdaContext
ctx
Either SomeException result
caughtResult <- m result -> m (Either SomeException result)
forall (m :: * -> *) e a.
(MonadCatch m, Exception e) =>
m a -> m (Either e a)
try (Value -> m result
fn Value
event)
Either String result -> m (Either String result)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String result -> m (Either String result))
-> Either String result -> m (Either String result)
forall a b. (a -> b) -> a -> b
$ (SomeException -> String)
-> Either SomeException result -> Either String result
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first (SomeException -> String
forall e. Exception e => e -> String
displayException :: SomeException -> String) Either SomeException result
caughtResult
IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ case Either String result
result of
Right result
r -> RuntimeClientConfig -> ByteString -> result -> IO ()
forall a.
ToJSON a =>
RuntimeClientConfig -> ByteString -> a -> IO ()
sendEventSuccess RuntimeClientConfig
runtimeClientConfig ByteString
reqIdBS result
r
Left String
e -> RuntimeClientConfig -> ByteString -> String -> IO ()
sendEventError RuntimeClientConfig
runtimeClientConfig ByteString
reqIdBS String
e
mRuntimeWithContext :: (HasLambdaContext r, MonadCatch m, MonadReader r m, MonadIO m, ToJSON result) =>
(Value -> m result) -> m ()
mRuntimeWithContext :: (Value -> m result) -> m ()
mRuntimeWithContext Value -> m result
fn = do
RuntimeClientConfig
runtimeClientConfig <- IO RuntimeClientConfig -> m RuntimeClientConfig
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO RuntimeClientConfig
getRuntimeClientConfig
m () -> m ()
forall (f :: * -> *) a b. Applicative f => f a -> f b
forever (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ RuntimeClientConfig -> (Value -> m result) -> m ()
forall r (m :: * -> *) result.
(HasLambdaContext r, MonadReader r m, MonadCatch m, MonadIO m,
ToJSON result) =>
RuntimeClientConfig -> (Value -> m result) -> m ()
runtimeLoop RuntimeClientConfig
runtimeClientConfig Value -> m result
fn
readerTRuntime :: ToJSON result =>
(Value -> ReaderT LambdaContext IO result) -> IO ()
readerTRuntime :: (Value -> ReaderT LambdaContext IO result) -> IO ()
readerTRuntime = ReaderT LambdaContext IO () -> IO ()
forall (m :: * -> *) a. ReaderT LambdaContext m a -> m a
runReaderTLambdaContext (ReaderT LambdaContext IO () -> IO ())
-> ((Value -> ReaderT LambdaContext IO result)
-> ReaderT LambdaContext IO ())
-> (Value -> ReaderT LambdaContext IO result)
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Value -> ReaderT LambdaContext IO result)
-> ReaderT LambdaContext IO ()
forall r (m :: * -> *) result.
(HasLambdaContext r, MonadCatch m, MonadReader r m, MonadIO m,
ToJSON result) =>
(Value -> m result) -> m ()
mRuntimeWithContext
ioRuntimeWithContext :: ToJSON result =>
(LambdaContext -> Value -> IO (Either String result)) -> IO ()
ioRuntimeWithContext :: (LambdaContext -> Value -> IO (Either String result)) -> IO ()
ioRuntimeWithContext = (Value -> ReaderT LambdaContext IO result) -> IO ()
forall result.
ToJSON result =>
(Value -> ReaderT LambdaContext IO result) -> IO ()
readerTRuntime ((Value -> ReaderT LambdaContext IO result) -> IO ())
-> ((LambdaContext -> Value -> IO (Either String result))
-> Value -> ReaderT LambdaContext IO result)
-> (LambdaContext -> Value -> IO (Either String result))
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (LambdaContext -> Value -> IO (Either String result))
-> Value -> ReaderT LambdaContext IO result
forall c (m :: * -> *) b a.
(MonadReader c m, MonadIO m) =>
(c -> b -> IO (Either String a)) -> b -> m a
withIOInterface
ioRuntime :: ToJSON result =>
(Value -> IO (Either String result)) -> IO ()
ioRuntime :: (Value -> IO (Either String result)) -> IO ()
ioRuntime = (Value -> ReaderT LambdaContext IO result) -> IO ()
forall result.
ToJSON result =>
(Value -> ReaderT LambdaContext IO result) -> IO ()
readerTRuntime ((Value -> ReaderT LambdaContext IO result) -> IO ())
-> ((Value -> IO (Either String result))
-> Value -> ReaderT LambdaContext IO result)
-> (Value -> IO (Either String result))
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (LambdaContext -> Value -> IO (Either String result))
-> Value -> ReaderT LambdaContext IO result
forall c (m :: * -> *) b a.
(MonadReader c m, MonadIO m) =>
(c -> b -> IO (Either String a)) -> b -> m a
withIOInterface ((LambdaContext -> Value -> IO (Either String result))
-> Value -> ReaderT LambdaContext IO result)
-> ((Value -> IO (Either String result))
-> LambdaContext -> Value -> IO (Either String result))
-> (Value -> IO (Either String result))
-> Value
-> ReaderT LambdaContext IO result
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Value -> IO (Either String result))
-> LambdaContext -> Value -> IO (Either String result)
forall a b. a -> b -> a
withoutContext
fallibleRuntimeWithContext :: ToJSON result =>
(LambdaContext -> Value -> Either String result) -> IO ()
fallibleRuntimeWithContext :: (LambdaContext -> Value -> Either String result) -> IO ()
fallibleRuntimeWithContext = (Value -> ReaderT LambdaContext IO result) -> IO ()
forall result.
ToJSON result =>
(Value -> ReaderT LambdaContext IO result) -> IO ()
readerTRuntime ((Value -> ReaderT LambdaContext IO result) -> IO ())
-> ((LambdaContext -> Value -> Either String result)
-> Value -> ReaderT LambdaContext IO result)
-> (LambdaContext -> Value -> Either String result)
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (LambdaContext -> Value -> Either String result)
-> Value -> ReaderT LambdaContext IO result
forall c (m :: * -> *) b a.
MonadReader c m =>
(c -> b -> Either String a) -> b -> m a
withFallibleInterface
fallibleRuntime :: ToJSON result =>
(Value -> Either String result) -> IO ()
fallibleRuntime :: (Value -> Either String result) -> IO ()
fallibleRuntime = (Value -> ReaderT LambdaContext IO result) -> IO ()
forall result.
ToJSON result =>
(Value -> ReaderT LambdaContext IO result) -> IO ()
readerTRuntime ((Value -> ReaderT LambdaContext IO result) -> IO ())
-> ((Value -> Either String result)
-> Value -> ReaderT LambdaContext IO result)
-> (Value -> Either String result)
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (LambdaContext -> Value -> Either String result)
-> Value -> ReaderT LambdaContext IO result
forall c (m :: * -> *) b a.
MonadReader c m =>
(c -> b -> Either String a) -> b -> m a
withFallibleInterface ((LambdaContext -> Value -> Either String result)
-> Value -> ReaderT LambdaContext IO result)
-> ((Value -> Either String result)
-> LambdaContext -> Value -> Either String result)
-> (Value -> Either String result)
-> Value
-> ReaderT LambdaContext IO result
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Value -> Either String result)
-> LambdaContext -> Value -> Either String result
forall a b. a -> b -> a
withoutContext
pureRuntimeWithContext :: ToJSON result =>
(LambdaContext -> Value -> result) -> IO ()
pureRuntimeWithContext :: (LambdaContext -> Value -> result) -> IO ()
pureRuntimeWithContext = (Value -> ReaderT LambdaContext IO result) -> IO ()
forall result.
ToJSON result =>
(Value -> ReaderT LambdaContext IO result) -> IO ()
readerTRuntime ((Value -> ReaderT LambdaContext IO result) -> IO ())
-> ((LambdaContext -> Value -> result)
-> Value -> ReaderT LambdaContext IO result)
-> (LambdaContext -> Value -> result)
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (LambdaContext -> Value -> result)
-> Value -> ReaderT LambdaContext IO result
forall c (m :: * -> *) b a.
MonadReader c m =>
(c -> b -> a) -> b -> m a
withPureInterface
pureRuntime :: ToJSON result => (Value -> result) -> IO ()
pureRuntime :: (Value -> result) -> IO ()
pureRuntime = (Value -> ReaderT LambdaContext IO result) -> IO ()
forall result.
ToJSON result =>
(Value -> ReaderT LambdaContext IO result) -> IO ()
readerTRuntime ((Value -> ReaderT LambdaContext IO result) -> IO ())
-> ((Value -> result) -> Value -> ReaderT LambdaContext IO result)
-> (Value -> result)
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (LambdaContext -> Value -> result)
-> Value -> ReaderT LambdaContext IO result
forall c (m :: * -> *) b a.
MonadReader c m =>
(c -> b -> a) -> b -> m a
withPureInterface ((LambdaContext -> Value -> result)
-> Value -> ReaderT LambdaContext IO result)
-> ((Value -> result) -> LambdaContext -> Value -> result)
-> (Value -> result)
-> Value
-> ReaderT LambdaContext IO result
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Value -> result) -> LambdaContext -> Value -> result
forall a b. a -> b -> a
withoutContext