public async Task RegisterSubscriber(string topic, string subscriberAddress)
        {
            m_log.Debug("Adding sqs subscriber {0} to sns topic {1}", subscriberAddress, topic);
            using (var rebusTransactionScope = new RebusTransactionScope())
            {
                var topicArn = await m_AmazonInternalSettings.GetTopicArn(topic, rebusTransactionScope);

                var destinationQueueUrlByName = m_amazonSQSQueueContext.GetDestinationQueueUrlByName(subscriberAddress, rebusTransactionScope.TransactionContext);

                var sqsInformation = m_amazonSQSQueueContext.GetSqsInformationFromUri(destinationQueueUrlByName);

                var snsClient = m_AmazonInternalSettings.CreateSnsClient(rebusTransactionScope.TransactionContext);

                var listSubscriptionsByTopicResponse = await snsClient.ListSubscriptionsByTopicAsync(topicArn);

                var subscriptions = listSubscriptionsByTopicResponse?.Subscriptions;

                var subscription = subscriptions?.FirstOrDefault(s => s.SubscriptionArn == sqsInformation.Arn);

                if (subscription == null)
                {
                    var subscribeResponse = await snsClient.SubscribeAsync(topicArn, "sqs", sqsInformation.Arn);

                    if (subscribeResponse.HttpStatusCode != HttpStatusCode.OK)
                    {
                        throw new SnsRebusException($"Error creating subscription {subscriberAddress} on topic {topic}.", subscribeResponse.CreateAmazonExceptionFromResponse());
                    }

                    await m_AmazonInternalSettings.CheckSqsPolicy(rebusTransactionScope.TransactionContext, destinationQueueUrlByName, sqsInformation, topicArn);

                    await snsClient.SetSubscriptionAttributesAsync(subscribeResponse.SubscriptionArn, "RawMessageDelivery", bool.TrueString);
                }
                else
                {
                    await snsClient.SetSubscriptionAttributesAsync(subscription.SubscriptionArn, "RawMessageDelivery", bool.TrueString);
                }
            }
            m_log.Debug("Added sqs subscriber {0} to sns topic {1}", subscriberAddress, topic);
        }
        public static async Task <string> GetTopicArn(this IAmazonInternalSettings amazonInternalSettings, string topic, RebusTransactionScope scope = null)
        {
            var result = await Task.FromResult(s_topicArnCache.GetOrAdd(topic, s =>
            {
                var rebusTransactionScope = scope ?? new RebusTransactionScope();
                try
                {
                    var logger = amazonInternalSettings.RebusLoggerFactory.GetLogger();

                    var snsClient = amazonInternalSettings.CreateSnsClient(rebusTransactionScope.TransactionContext);

                    var formatedTopicName = amazonInternalSettings.TopicFormatter.FormatTopic(topic);

                    var findTopicAsync = snsClient.FindTopicAsync(formatedTopicName);

                    AsyncHelpers.RunSync(() => findTopicAsync);

                    var findTopicResult = findTopicAsync.Result;

                    string topicArn = findTopicResult?.TopicArn;

                    if (findTopicResult == null)
                    {
                        logger.Debug($"Did not find sns topic {0}", formatedTopicName);
                        var task = snsClient.CreateTopicAsync(new CreateTopicRequest(formatedTopicName));
                        AsyncHelpers.RunSync(() => task);
                        topicArn = task.Result?.TopicArn;
                        logger.Debug($"Created sns topic {0} => {1}", formatedTopicName, topicArn);
                    }

                    logger.Debug($"Using sns topic {0} => {1}", formatedTopicName, topicArn);
                    return(topicArn);
                }
                finally
                {
                    if (scope == null)
                    {
                        rebusTransactionScope.Dispose();
                    }
                }
            }));

            return(result);
        }
        public async Task SendAsync(TransportMessage message, ITransactionContext context)
        {
            var snsClient = _amazonInternalSettings.CreateSnsClient(context);

            var sqsMessage = new AmazonTransportMessage(message.Headers, StringHelper.GetBody(message.Body));

            var msg = _amazonInternalSettings.MessageSerializer.Serialize(sqsMessage);

            var pubRequest = new PublishRequest(_destinationAddress, msg);

            var messageAttributeValues = context.GetOrNull <IDictionary <string, MessageAttributeValue> >(SnsAttributeMapperOutBoundStep.SnsAttributeKey) ?? new Dictionary <string, MessageAttributeValue>();

            foreach (var messageAttributeValue in messageAttributeValues)
            {
                pubRequest.MessageAttributes.Add(messageAttributeValue.Key, messageAttributeValue.Value);
            }
            var publishResponse = await snsClient.PublishAsync(pubRequest);

            if (publishResponse.HttpStatusCode != HttpStatusCode.OK)
            {
                throw new SnsRebusException($"Error publishing message to topic {_destinationAddress}.", publishResponse.CreateAmazonExceptionFromResponse());
            }
        }