choonkeat / elm-aws / AWS.SQS

Implementation of https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-working-with-apis.html


type OutgoingMessage
    = StandardMessage ({ body : String, attributes : List { name : String, type_ : String, value : String } })
    | FifoMessage ({ body : String, attributes : List { name : String, type_ : String, value : String }, messageGroupId : String })


type Response
    = Error ({ type_ : String, code : String, message : String })
    | Success ({ messageIds : List String, requestId : String })

Response from SES API

See https://docs.aws.amazon.com/ses/latest/DeveloperGuide/using-ses-api-responses.html

unsignedRequest : Url -> List OutgoingMessage -> AWS.Types.UnsignedRequest Http.Error Response

Construct an UnsignedRequest for SQS https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessageBatch.html, e.g.

import Http
import AWS.Types
import Url

queueUrl : Url.Url
queueUrl =
    { protocol = Url.Https
    , host = "somequeue"
    , port_ = Nothing
    , path = "/123/queue.fifo"
    , query = Nothing
    , fragment = Nothing
    }

unsignedResult : AWS.Types.UnsignedRequest Http.Error Response
unsignedResult =
    unsignedRequest queueUrl
        [ StandardMessage
            { body = "alpha message"
            , attributes = [ { name = "nameA", type_ = "typeA", value = "valueA" }]
            }
        , FifoMessage
            { body = "beta message"
            , attributes = [ { name = "nameB", type_ = "typeB", value = "valueB" }]
            , messageGroupId = "messageGroupABC"
            }
        ]

unsignedResult.method
--> "POST"

unsignedResult.headers
--> [("Content-Type","application/x-www-form-urlencoded")]

unsignedResult.stringBody
--> "Action=SendMessageBatch&SendMessageBatchRequestEntry.1.Id=1&SendMessageBatchRequestEntry.1.MessageBody=alpha%20message&SendMessageBatchRequestEntry.2.Id=2&SendMessageBatchRequestEntry.2.MessageBody=beta%20message&SendMessageBatchRequestEntry.2.MessageGroupId=messageGroupABC"

unsignedResult.service
--> AWS.Types.ServiceSQS queueUrl


usage config now unsignedResult =
    unsignedResult
        |> Result.andThen (AWS.signRequest config now)
        |> Result.map Http.task

Tested internals

paramsForMessages : List OutgoingMessage -> List ( String, String )

expectedParams : List ( String, String )
expectedParams =
    [ ("Action","SendMessageBatch")
    , ("SendMessageBatchRequestEntry.1.Id","1")
    , ("SendMessageBatchRequestEntry.1.MessageBody","alpha message")
    , ("SendMessageBatchRequestEntry.1.MessageGroupId","MessageGroup123")
    , ("SendMessageBatchRequestEntry.2.Id","2")
    , ("SendMessageBatchRequestEntry.2.MessageBody","beta message")
    ]

paramsForMessages
    [ FifoMessage
        { body = "alpha message"
        , attributes = [ { name = "nameA", type_ = "typeA", value = "valueA" }]
        , messageGroupId = "MessageGroup123"
        }
    , StandardMessage
        { body = "beta message"
        , attributes = [ { name = "nameB", type_ = "typeB", value = "valueB" }]
        }
    ]
--> expectedParams

decodeResponse : Xml.Decode.Decoder Response

import Xml.Decode

--
-- Success scenario
"""
<SendMessageBatchResponse>
<SendMessageBatchResult>
    <SendMessageBatchResultEntry>
        <Id>test_msg_001</Id>
        <MessageId>0a5231c7-8bff-4955-be2e-8dc7c50a25fa</MessageId>
        <MD5OfMessageBody>0e024d309850c78cba5eabbeff7cae71</MD5OfMessageBody>
    </SendMessageBatchResultEntry>
    <SendMessageBatchResultEntry>
        <Id>test_msg_002</Id>
        <MessageId>15ee1ed3-87e7-40c1-bdaa-2e49968ea7e9</MessageId>
        <MD5OfMessageBody>7fb8146a82f95e0af155278f406862c2</MD5OfMessageBody>
        <MD5OfMessageAttributes>295c5fa15a51aae6884d1d7c1d99ca50</MD5OfMessageAttributes>
    </SendMessageBatchResultEntry>
</SendMessageBatchResult>
<ResponseMetadata>
    <RequestId>ca1ad5d0-8271-408b-8d0f-1351bf547e74</RequestId>
</ResponseMetadata>
</SendMessageBatchResponse>
"""
|> Xml.Decode.run decodeResponse
--> Ok (Success { messageIds = ["test_msg_001","test_msg_002"], requestId = "ca1ad5d0-8271-408b-8d0f-1351bf547e74" })

--
-- Error scenario
"""
<ErrorResponse>
   <Error>
      <Type>
         Sender
      </Type>
      <Code>
         ValidationError
      </Code>
      <Message>
         Value null at 'message.subject' failed to satisfy constraint: Member must not be null
      </Message>
   </Error>
   <RequestId>
      42d59b56-7407-4c4a-be0f-4c88daeea257
   </RequestId>
</ErrorResponse>
"""
|> Xml.Decode.run decodeResponse
--> Ok (Error  { type_ = "Sender", code = "ValidationError", message = "Value null at 'message.subject' failed to satisfy constraint: Member must not be null" })