{-# LANGUAGE TypeApplications #-}
module AWSLambda.Handler
( lambdaMain
) where
import Control.Exception (bracket, try)
import qualified Data.Aeson as Aeson
import qualified Data.Aeson.Text as Aeson
import qualified Data.ByteString as ByteString
import qualified Data.Text.Lazy.IO as Text
import GHC.IO.Handle
(BufferMode(..), Handle, hClose, hSetBuffering)
import System.IO (stdout)
import System.Posix.Files (getFdStatus)
import System.Posix.IO (fdToHandle)
import System.Posix.Types (Fd(..))
lambdaMain ::
(Aeson.FromJSON event, Aeson.ToJSON res)
=> (event -> IO res)
-> IO ()
lambdaMain :: (event -> IO res) -> IO ()
lambdaMain event -> IO res
act =
(Handle -> IO ()) -> IO ()
forall r. (Handle -> IO r) -> IO r
withResultChannel ((Handle -> IO ()) -> IO ()) -> (Handle -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Handle
resultChannel -> do
ByteString
input <- IO ByteString
ByteString.getLine
case ByteString -> Either String event
forall a. FromJSON a => ByteString -> Either String a
Aeson.eitherDecodeStrict ByteString
input of
Left String
err -> String -> IO ()
forall a. HasCallStack => String -> a
error String
err
Right event
event -> do
res
result <- event -> IO res
act event
event
Handle -> Text -> IO ()
Text.hPutStrLn Handle
resultChannel (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ res -> Text
forall a. ToJSON a => a -> Text
Aeson.encodeToLazyText res
result
() -> IO ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
withResultChannel :: (Handle -> IO r) -> IO r
withResultChannel :: (Handle -> IO r) -> IO r
withResultChannel Handle -> IO r
act = do
Either IOError FileStatus
commStatus <- forall a. Exception IOError => IO a -> IO (Either IOError a)
forall e a. Exception e => IO a -> IO (Either e a)
try @IOError (IO FileStatus -> IO (Either IOError FileStatus))
-> IO FileStatus -> IO (Either IOError FileStatus)
forall a b. (a -> b) -> a -> b
$ Fd -> IO FileStatus
getFdStatus Fd
communicationFd
case Either IOError FileStatus
commStatus of
Right FileStatus
_ -> do
Handle -> BufferMode -> IO ()
hSetBuffering Handle
stdout BufferMode
LineBuffering
IO Handle -> (Handle -> IO ()) -> (Handle -> IO r) -> IO r
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket (Fd -> IO Handle
fdToHandle Fd
communicationFd) Handle -> IO ()
hClose Handle -> IO r
act
Left IOError
_ -> Handle -> IO r
act Handle
stdout
communicationFd :: Fd
communicationFd :: Fd
communicationFd = CInt -> Fd
Fd CInt
3