module Network.PinPon.AWS
( runSNS
) where
import Protolude hiding (catch)
import Control.Lens ((^.))
import Control.Monad.Catch (catch)
import Control.Monad.Reader (asks)
import Control.Monad.Trans.AWS (runAWST, send)
import qualified Data.ByteString.Lazy as BL (ByteString)
import Data.ByteString.Lens (packedChars)
import Network.AWS.Data.Text (ToText(..))
import Network.AWS.Types (AWSRequest, Error(..), Rs, serializeMessage, serviceMessage)
import Network.HTTP.Client (HttpException(..), HttpExceptionContent(..))
import Servant (ServantErr(..), err502, err504, throwError)
import Network.PinPon.Config (App(..), Config(..))
runSNS :: (AWSRequest a) => a -> App (Rs a)
runSNS req =
do env <- asks _env
catch (runAWST env $ send req) $ throwError . snsErrToServant
snsErrToServant :: Error -> ServantErr
snsErrToServant e = (errCode e) { errBody = mconcat ["Upstream AWS SNS error: ", errMsg e ] }
errCode :: Error -> ServantErr
errCode (TransportError (HttpExceptionRequest _ ResponseTimeout)) = err504
errCode (TransportError (HttpExceptionRequest _ ConnectionTimeout)) = err504
errCode _ = err502
errMsg :: Error -> BL.ByteString
errMsg (ServiceError e) = maybe "Unspecified error" (toSL . toText) $ e ^. serviceMessage
errMsg (SerializeError e) = e ^. serializeMessage ^. packedChars
errMsg (TransportError e) = show e ^. packedChars