예제 #1
0
 async Task DeleteMessage(SqsReceivedDelayedMessage messageToDeleteWithAnotherAttempt)
 {
     try
     {
         // should not be cancelled
         await sqsClient.DeleteMessageAsync(messageToDeleteWithAnotherAttempt.QueueUrl, messageToDeleteWithAnotherAttempt.ReceiptHandle).ConfigureAwait(false);
     }
     catch (ReceiptHandleIsInvalidException ex)
     {
         Logger.Info($"Message receipt handle '{messageToDeleteWithAnotherAttempt.ReceiptHandle}' no longer valid.", ex);
     }
 }
예제 #2
0
        IReadOnlyCollection <SqsReceivedDelayedMessage> PrepareMessages(CancellationToken token, ReceiveMessageResponse receivedMessages, TimeSpan clockCorrection)
        {
            List <SqsReceivedDelayedMessage> preparedMessages = null;

            foreach (var receivedMessage in receivedMessages.Messages)
            {
                token.ThrowIfCancellationRequested();

                preparedMessages = preparedMessages ?? new List <SqsReceivedDelayedMessage>(receivedMessages.Messages.Count);
                long delaySeconds = 0;

                if (receivedMessage.MessageAttributes.TryGetValue(TransportHeaders.DelaySeconds, out var delayAttribute))
                {
                    long.TryParse(delayAttribute.StringValue, out delaySeconds);
                }

                string originalMessageId = null;
                if (receivedMessage.MessageAttributes.TryGetValue(Headers.MessageId, out var messageIdAttribute))
                {
                    originalMessageId = messageIdAttribute.StringValue;
                }

                var sent     = receivedMessage.GetAdjustedDateTimeFromServerSetAttributes("SentTimestamp", clockCorrection);
                var received = receivedMessage.GetAdjustedDateTimeFromServerSetAttributes("ApproximateFirstReceiveTimestamp", clockCorrection);

                if (Convert.ToInt32(receivedMessage.Attributes["ApproximateReceiveCount"]) > 1)
                {
                    received = DateTime.UtcNow;
                }

                var elapsed = received - sent;

                var remainingDelay = delaySeconds - (long)elapsed.TotalSeconds;

                SqsReceivedDelayedMessage preparedMessage;

                if (remainingDelay > configuration.DelayedDeliveryQueueDelayTime)
                {
                    preparedMessage = new SqsReceivedDelayedMessage(originalMessageId, receivedMessage.ReceiptHandle)
                    {
                        QueueUrl          = delayedDeliveryQueueUrl,
                        MessageAttributes =
                        {
                            [TransportHeaders.DelaySeconds] = new MessageAttributeValue
                            {
                            StringValue = remainingDelay.ToString(),
                            DataType    = "String"
                            }
                        }
                    };

                    var deduplicationId = receivedMessage.Attributes["MessageDeduplicationId"];

                    // this is only here for acceptance testing purpose. In real prod code this is always false.
                    // it allows us to fake multiple cycles over the FIFO queue without being subjected to deduplication
                    if (configuration.DelayedDeliveryQueueDelayTime < TransportConfiguration.AwsMaximumQueueDelayTime)
                    {
                        deduplicationId = Guid.NewGuid().ToString();
                    }

                    preparedMessage.MessageDeduplicationId = preparedMessage.MessageGroupId = deduplicationId;
                }
                else
                {
                    preparedMessage = new SqsReceivedDelayedMessage(originalMessageId, receivedMessage.ReceiptHandle)
                    {
                        QueueUrl = inputQueueUrl
                    };

                    if (remainingDelay > 0)
                    {
                        preparedMessage.DelaySeconds = Convert.ToInt32(remainingDelay);
                    }
                }

                if (string.IsNullOrEmpty(originalMessageId))
                {
                    // for backward compatibility if we couldn't fetch the message id header from the attributes we use the message deduplication id
                    originalMessageId = receivedMessage.Attributes["MessageDeduplicationId"];
                }

                // because message attributes are part of the content size restriction we want to prevent message size from changing thus we add it
                // for native delayed deliver as well
                preparedMessage.MessageAttributes[Headers.MessageId] = new MessageAttributeValue
                {
                    StringValue = originalMessageId,
                    DataType    = "String"
                };

                preparedMessage.Body = receivedMessage.Body;
                preparedMessage.CalculateSize();

                preparedMessages.Add(preparedMessage);
            }

            return(preparedMessages);
        }