//--- Methods --- public override Task InitializeAsync(LambdaConfig config) { var sqsClient = new AmazonSQSClient(); var queueName = AwsConverters.ConvertQueueArnToUrl(config.ReadText("SqsSongQueue")); SpeakerRequest = new SpeakerRequest(this, sqsClient, queueName); return(Task.CompletedTask); }
//--- Constructors --- public override Task InitializeAsync(LambdaConfig config) { var queueName = AwsConverters.ConvertQueueArnToUrl(config.ReadText("SqsSongQueue")); var tableName = AwsConverters.ConvertDynamoDBArnToName(config.ReadText("DynamoDbSongs")); var indexNameSearchTitle = config.ReadText("DynamoDbIndexNameSearchTitleName"); var indexNameSearchTitleArtist = config.ReadText("DynamoDbIndexNameSearchTitleArtistName"); var indexTableName = AwsConverters.ConvertDynamoDBArnToName(config.ReadText("DynamoDbTitleWordCache")); _jukeboxDynamoDb = new JukeboxDynamoDb(new AmazonDynamoDBClient(), tableName, indexNameSearchTitle, indexNameSearchTitleArtist, indexTableName); _playSongRequest = new PlaySongTitleRequest(this, new AmazonSQSClient(), queueName, this); return(Task.CompletedTask); }
/// <summary> /// The <see cref="ProcessMessageStreamAsync(Stream)"/> method is overridden to /// provide specific behavior for this base class. /// </summary> /// <remarks> /// This method cannot be overridden. /// </remarks> /// <param name="stream">The stream with the request payload.</param> /// <returns>The task object representing the asynchronous operation.</returns> public override sealed async Task <Stream> ProcessMessageStreamAsync(Stream stream) { var failureCounter = 0; // deserialize stream to sqs event LogInfo("deserializing stream to SQS event"); var sqsEvent = DeserializeJson <SQSEvent>(stream); // process all received sqs records var successfulMessages = new List <SQSEvent.SQSMessage>(); foreach (var sqsRecord in sqsEvent.Records) { CurrentRecord = sqsRecord; try { // attempt to deserialize the sqs record LogInfo("deserializing message"); var message = Deserialize(sqsRecord.Body); // attempt to process the sqs message LogInfo("processing message"); await ProcessMessageAsync(message); successfulMessages.Add(sqsRecord); } catch (LambdaRetriableException e) { // record error as warning; function will need to fail to prevent deletion LogErrorAsWarning(e); ++failureCounter; } catch (Exception e) { LogError(e); // send straight to the dead letter queue and prevent from re-trying try { await RecordFailedMessageAsync(LambdaLogLevel.ERROR, FailedMessageOrigin.SQS, SerializeJson(sqsRecord), e); successfulMessages.Add(sqsRecord); } catch { // no dead-letter queue configured; function will need to fail to prevent deletion ++failureCounter; } } finally { CurrentRecord = null; } } // check if any failures occurred if (failureCounter > 0) { // delete all messages that were successfully processed to avoid them being tried again if (successfulMessages.Count > 0) { await Provider.DeleteMessagesFromQueueAsync( AwsConverters.ConvertQueueArnToUrl(successfulMessages.First().EventSourceArn), successfulMessages.Select(message => (MessageId: message.MessageId, ReceiptHandle: message.ReceiptHandle) ) ); } // fail invocation to prevent messages from being deleted throw new LambdaAbortException($"processing failed: {failureCounter} errors ({successfulMessages.Count} messages succeeded)"); } return($"processed {successfulMessages.Count} messages".ToStream()); }