/// <summary> /// Creates the SQS queue. If the queue already exists, the existing URL is returned. /// </summary> /// <param name="awsCredentials">The AWS credentials for access the queue.</param> /// <returns>System.String.</returns> /// <exception cref="System.InvalidOperationException">Unable to create SQS queue</exception> private string GetSqsQueueUrl(AWSCredentials awsCredentials) { Logger.LogDebug($"Getting SQS Queue: {AwsSettings.Sqs.Name}"); Logger.LogDebug($"Using AWS Region: {AwsSettings.Sqs.Region}"); sqsClient = new SQS.AmazonSQSClient(awsCredentials, RegionEndpoint.GetBySystemName(AwsSettings.Sqs.Region)); var queueUrlResponse = AsyncTaskHelper.RunSync(() => sqsClient.GetQueueUrlAsync(AwsSettings.Sqs.Name)); Logger.LogTrace($"SQS Queue Response[Status:{queueUrlResponse.HttpStatusCode}], [QueueUrl:{queueUrlResponse.QueueUrl}]"); if (queueUrlResponse.HttpStatusCode != HttpStatusCode.OK) { Logger.LogError($"Error getting SQS Queue. Status code: {queueUrlResponse.HttpStatusCode}. Aborting."); throw new InvalidOperationException("Unable to open SQS queue"); } return(queueUrlResponse.QueueUrl); }
/// <summary> /// The main entrypoint for the thread that listens to messages. /// </summary> private void AWSMessageListener() { // Used to eliminate over logging bool receivedMessage = true; while (!stopping) { try { var receiveMessageRequest = new SQS.Model.ReceiveMessageRequest() { WaitTimeSeconds = 10, QueueUrl = sqsQueueUrl }; if (receivedMessage) { Logger.LogTrace("Waiting for message from queue"); } receivedMessage = false; var messageResponse = AsyncTaskHelper.RunSync(() => sqsClient.ReceiveMessageAsync(receiveMessageRequest)); if (messageResponse.HttpStatusCode == HttpStatusCode.OK && messageResponse.Messages.Count > 0 && !stopping) { receivedMessage = true; Logger.LogDebug($"Received {messageResponse.Messages.Count} message(s)"); foreach (var messageResponseMessage in messageResponse.Messages) { try { ProcessMessage(messageResponseMessage); } finally { #if (!DONTDELETEMESSAGE) // Delete the message even in error since it will keep coming back // Perhaps a better action would be to put in a dead letter queue DeleteMessage(messageResponseMessage); #endif } } } } catch (Exception ex) { Logger.LogError("Error processing message: {0}", ex); } } // Process the received message void ProcessMessage(SQS.Model.Message messageResponseMessage) { Logger.LogTrace($"Received Message ({messageResponseMessage.MessageId}): {messageResponseMessage.Body}"); var snsMessage = SNS.Util.Message.ParseMessage(messageResponseMessage.Body); var feedEvent = JsonConvert.DeserializeObject <FeedEvent>(snsMessage.MessageText); Logger.LogInformation($"Feed: {feedEvent.Feed}, Event: {feedEvent.Event}, Package: {feedEvent.Package}, Version: {feedEvent.Version}"); Logger.LogTrace($"Package URL: {feedEvent.PackageUrl}"); var actionableActions = ApplicationSettings.Actions.Where(action => string.Equals(action.SourceFeed, feedEvent.Feed, StringComparison.InvariantCultureIgnoreCase) && action.Enabled); Package retrievedPackage = null; foreach (var actionableAction in actionableActions) { Logger.LogTrace($"Found Action ({actionableAction.Name}) for {feedEvent.Feed}"); if (feedEvent.Version.IsPrerelease() && !actionableAction.IncludePrerelease) { Logger.LogDebug($"{actionableAction.Name} is ignoring prelease package ({feedEvent.Package}.{feedEvent.Version})"); continue; } using (var scope = ServiceProvider.CreateScope()) { var action = ActionProcessor.CreateAction(scope, actionableAction); switch (feedEvent.Event) { case EventType.Added: if (retrievedPackage == null) { retrievedPackage = AsyncTaskHelper.RunSync(() => action.SourceRepository.FetchAsync(feedEvent.Package, feedEvent.Version)); } if (retrievedPackage == null) { Logger.LogWarning($"{feedEvent.Package}.{feedEvent.Version} not found in feed {feedEvent.Feed}. Ignoring."); } else { AsyncTaskHelper.RunSync(() => action.ProcessPackageAsync(retrievedPackage, PackageEvent.Added)); } break; case EventType.Deleted: case EventType.Purged: // We can't retrieve the package because it has been deleted var deletePackage = new Package { Id = feedEvent.Package, Version = feedEvent.Version }; AsyncTaskHelper.RunSync(() => action.ProcessPackageAsync(deletePackage, PackageEvent.Deleted)); break; } } } } #if (!DONTDELETEMESSAGE) // Delete the processed message from the queue void DeleteMessage(SQS.Model.Message messageResponseMessage) { var deleteMessageRequest = new SQS.Model.DeleteMessageRequest { QueueUrl = sqsQueueUrl, ReceiptHandle = messageResponseMessage.ReceiptHandle }; Logger.LogTrace($"Deleting Message: {messageResponseMessage.ReceiptHandle}"); var deleteMessageResponse = AsyncTaskHelper.RunSync(() => sqsClient.DeleteMessageAsync(deleteMessageRequest)); if (deleteMessageResponse.HttpStatusCode == HttpStatusCode.OK) { Logger.LogTrace($"Delete Message: {messageResponseMessage.ReceiptHandle}"); } else { Logger.LogWarning($"Unable to delete Message: {messageResponseMessage.ReceiptHandle}. Ignoring."); } } #endif }