private void SubscribeToTopic(AmazonSQSClient sqsClient, AmazonSimpleNotificationServiceClient snsClient) { var subscription = snsClient.SubscribeQueueAsync(_channelTopicArn, sqsClient, _queueUrl).Result; if (!string.IsNullOrEmpty(subscription)) { //We need to support raw messages to allow the use of message attributes var response = snsClient.SetSubscriptionAttributesAsync( new SetSubscriptionAttributesRequest( subscription, "RawMessageDelivery", "true") ) .Result; if (response.HttpStatusCode != HttpStatusCode.OK) { throw new InvalidOperationException($"Unable to set subscription attribute for raw message delivery"); } } else { throw new InvalidOperationException( $"Could not subscribe to topic: {_channelTopicArn} from queue: {_queueUrl} in region {_awsConnection.Region}"); } }
public async Task <string> SubscribeQueueAsync(string topicArn, string sqsQueueUrl) { return(await snsClient.SubscribeQueueAsync(topicArn, this.sqsService.GetSqsClient(), sqsQueueUrl)); }
private void EnsureQueue(Connection connection) { using (var sqsClient = new AmazonSQSClient(_awsConnection.Credentials, _awsConnection.Region)) { //Does the queue exist - this is an HTTP call, we should cache the results for a period of time (bool exists, string name)queueExists = QueueExists(sqsClient, connection.ChannelName.ToValidSQSQueueName()); if (!queueExists.exists) { try { var request = new CreateQueueRequest(connection.ChannelName.ToValidSQSQueueName()) { Attributes = { { "VisibilityTimeout", connection.VisibilityTimeout.ToString() }, { "ReceiveMessageWaitTimeSeconds", ToSecondsAsString(connection.TimeoutInMiliseconds) } } }; var response = sqsClient.CreateQueueAsync(request).Result; var queueUrl = response.QueueUrl; if (!string.IsNullOrEmpty(queueUrl)) { //topic might not exist using (var snsClient = new AmazonSimpleNotificationServiceClient(_awsConnection.Credentials, _awsConnection.Region)) { var exists = snsClient.ListTopicsAsync().Result.Topics.SingleOrDefault(topic => topic.TopicArn == connection.RoutingKey); if (exists == null) { var createTopic = snsClient.CreateTopicAsync(new CreateTopicRequest(connection.RoutingKey.ToValidSNSTopicName())).Result; if (!string.IsNullOrEmpty(createTopic.TopicArn)) { var subscription = snsClient.SubscribeQueueAsync(createTopic.TopicArn, sqsClient, queueUrl).Result; //We need to support raw messages to allow the use of message attributes snsClient.SetSubscriptionAttributesAsync(new SetSubscriptionAttributesRequest(subscription, "RawMessageDelivery", "true")); } } } } } catch (AggregateException ae) { //TODO: We need some retry semantics here //TODO: We need to flatten the ae and handle some of these with ae.Handle((x) => {}) ae.Handle(ex => { if (ex is QueueDeletedRecentlyException) { //QueueDeletedRecentlyException - wait 30 seconds then retry //Although timeout is 60s, we could be partway through that, so apply Copernican Principle //and assume we are halfway through var error = $"Could not create queue {connection.ChannelName.ToValidSQSQueueName()} because {ae.Message} waiting 60s to retry"; _logger.Value.Error(error); Task.Delay(TimeSpan.FromSeconds(30)); throw new ChannelFailureException(error, ae); } return(false); }); } } } }