Serverless Patterns implemented: using an SQS queue as a DLQ for a SNS topic
Contents
In the last two articles (here and here) we implemented some of the Serverless Patterns described in this article from Jeremy Daly. In this article, we’re going to concentrate in just one pattern, the Notifier. We’re going to do this, because of the [recent announcement] from AWS that you can now use an SQS queue as a Dead Letter Queue for an SNS topic.
If you read the article, you will see that this DLQ is complementary to the DLQ you might define in a function that is triggered by an SNS topic, as Otavio Ferreira explains here. As we saw the lambda function DLQ in a previous article, we’re going to focus on the DLQ of the topic. In this scenario, messages will be sent to the DLQ when SNS is not able to deliver the message to the subscribed endpoint. As this article explain, this can happen because the endpoint is not available, which is what we’re going to simulate. (client error) or because system responsible for the subscribed endpoint becomes unavailable or returns an exception that indicates that it can’t process a valid request from Amazon SNS (server error). In both cases, the message will be sent to the SNS topic DLQ. We can’t simulate a failure on a AWS Service, so we’re going to simulate that the endpoint of the subscription is not available.
In this article we’re going to see how we can implement this using the Serverless framework. As it’s a very new feature of the SNS topics, is not yet implemented, so we’re going to need to write quite a bit of CloudFormation. I’m sure the folks from Serverless are already working on making this easier to use.
Setup
As usual, let’s do the basic steps to setup our project. Let’s start initializing the nodejs project.
|
|
Then install the serverless framework as a dev dependency
|
|
And finally create a script to deploy the project
|
|
(Assuming that you have a profile called serverless-local, of course).
We will need the serverless-pseudo-parameters
plugin as well, so let’s install it:
|
|
Now, create a file called serverless.yml
and include the usual boilerplate code:
|
|
SNS Topic
Let’s start defining the SNS topic in the resource section of the file. It should look like this:
|
|
Nothing really strange here.
Now, it’s time to declare the SQS queue we’re going to use as DLQ for our topic
|
|
The next step would be to create the subscription in the SNS topic. The subscription is where we define where do we want the messages to be delivered.
|
|
In this case we’re going to define that we’ll have a lambda that will be responsible to receive these messages. There are two interesting parts here. The first one is that in the Endpoint section we’re defining a lambda that it really doesn’t exist. The second one is the RedrivePolice section, where we define the Dead Letter Queue of the topic, in this case the SQS queue previously defined.
For this topic to be able to put messages to a lambda (although in the subscription we’re simulating that the lambda doesn’t exist for some reason) we need to define a lambda permission:
|
|
The lambda resource needs to be already created, that´s why we put the DependsOn clause. You can´t reference a resource created by the serverless framework directly in a CloudFormation resource, but you can do the trick to use the name that the framework will use for the lambda. In this case, is the name of the function with LambdaFunction
concatenated.
(for the purpose of this particular example you can skip this step, but in case you want to see how the messages are delivered to a lambda with no issues, you will need to add it).
Finally, for the SNS topic to be able to deliver messages to the SQS DLQ we need to define an SQS Queue Policy, where we will tell SQS to allow messages comming from the SNS Topic:
|
|
Finally, and outside the resources section, we can define the functions that will read messages from the SNS Topic and the SQS Queue:
|
|
And the code of both functions. This is the code of the readFromSNS function:
|
|
And this is the code of the readFromDLQ function:
|
|
If we deploy, the serverless framework would have been added the subscription for the ReadFromSNS lambda in the SNS topic. You can delete it manually if you want to make sure that the message never gets there.
And that’s it. If you now try to put a message in the topic (using the console, or the CLI, or the SDK) you will see that the message ends up in the DLQ.
You can check the code here.
Summary
In this article, we’ve seen how we can define a SNS Queue as a Dead Letter Queue for an SNS topic. I expect this to not be needed in a near future because the Serverless framework will take care of it, but it’s never bad to know the internals and, in the meantime it gets implemented, you will be able to take care of this situations with the code we’ve seen in this article.
Hope it helps!!
Author Vicenç García
LastMod 26-11-2019