Originally posted on: http://geekswithblogs.net/EltonStoneman/archive/2013/10/13/aws-.net-sdk-v2-setting-up-queues-and-topics.aspxFollowing on from my last post, reading from SQS queues with the new SDK is easy stuff, but linking a Simple Notification Service topic to an SQS queue is a bit more involved. The AWS model for topics and subscriptions is a bit more advanced than in Azure Service Bus. SNS lets you have subscribers on multiple different channels, so you can send a message which gets relayed to email address, mobile apps and SQS queues all in one go.
As the topic owner, when you request a subscription on any channel, the owner needs to confirm they’re happy for you to send them messages. With email subscriptions, the user gets a confirmation request from Amazon which they need to reply to before they start getting messages. With SQS, you need to grant the topic permission to write to the queue. If you own both the topic and the queue, you can do it all in code with the .NET SDK.
Let’s say you want to create a new topic, a new queue as a topic subscriber, and link the two together. Creating the topic is easy with the SNS client (which has an expanded name, AmazonSimpleNotificationServiceClient, compare to the SQS class which is just called QueueClient): var request = new CreateTopicRequest();
request.Name = TopicName;
var response = _snsClient.CreateTopic(request);
TopicArn = response.TopicArn;
In the response from AWS (which I’m assuming is successful), you get an ARN – Amazon Resource Name – which is the unique identifier for the topic. We create the queue using the same code from my last post, AWS .NET SDK v2: the message-pump pattern, and then we need to subscribe the queue to the topic. The topic creates the subscription request: var response = _snsClient.Subscribe(new SubscribeRequest
{
TopicArn = TopicArn,
Protocol = "sqs",
Endpoint = _queueClient.QueueArn
});
That response will give you an ARN for the subscription, which you’ll need if you want to set attributes like RawMessageDelivery. Then the SQS client needs to confirm the subscription by allowing the topic to send messages to it. The SDK doesn’t give you a nice mechanism for doing that, so I’ve extended my AWS wrapper with a method that encapsulates it: internal void AllowSnsToSendMessages(TopicClient topicClient)
{
var policy = Policies.AllowSendFormat.Replace("%QueueArn%", QueueArn).Replace("%TopicArn%", topicClient.TopicArn);
var request = new SetQueueAttributesRequest();
request.Attributes.Add("Policy", policy);
request.QueueUrl = QueueUrl;
var response = _sqsClient.SetQueueAttributes(request);
}
That builds up a policy statement, which gets added to the queue as an attribute, and specifies that the topic is allowed to send messages to the queue. The statement itself is a JSON block which contains the ARN of the queue, the ARN of the topic, and an Allow effect for the sqs:SendMessage action:
public const string AllowSendFormat= @"{
""Statement"": [
{
""Sid"": ""MySQSPolicy001"",
""Effect"": ""Allow"",
""Principal"": {
""AWS"": ""*""
},
""Action"": ""sqs:SendMessage"",
""Resource"": ""%QueueArn%"",
""Condition"": {
""ArnEquals"": {
""aws:SourceArn"": ""%TopicArn%""
}
}
}
]
}";
There’s a new gist with an updated QueueClient and a new TopicClient here: Wrappers for the SQS and SNS clients in the AWS SDK for .NET v2. Both clients have an Ensure() method which creates the resource, so if you want to create a topic and a subscription you can use: var topicClient = new TopicClient(“BigNews”, “ImListening”);
And the topic client has a Subscribe() method, which calls into the message pump on the queue client: topicClient.Subscribe(x=>Log.Debug(x.Body));
var message = {}; //etc.
topicClient.Publish(message);
So you can isolate all the fiddly bits and use SQS and SNS with a similar interface to the Azure SDK.