static SendMessageBatchRequestEntry ToBatchEntry(this SqsPreparedMessage message, string batchEntryId)
 {
     return(new SendMessageBatchRequestEntry(batchEntryId, message.Body)
     {
         MessageAttributes = message.MessageAttributes,
         MessageGroupId = message.MessageGroupId,
         MessageDeduplicationId = message.MessageDeduplicationId,
         DelaySeconds = message.DelaySeconds
     });
 }
 public static SendMessageRequest ToRequest(this SqsPreparedMessage message)
 {
     return(new SendMessageRequest(message.QueueUrl, message.Body)
     {
         MessageGroupId = message.MessageGroupId,
         MessageDeduplicationId = message.MessageDeduplicationId,
         MessageAttributes = message.MessageAttributes,
         DelaySeconds = message.DelaySeconds
     });
 }
예제 #3
0
        public static IReadOnlyList <BatchEntry> Batch(IEnumerable <SqsPreparedMessage> preparedMessages)
        {
            var allBatches = new List <BatchEntry>();
            var currentDestinationBatches = new Dictionary <string, SqsPreparedMessage>();

            var groupByDestination = preparedMessages.GroupBy(m => m.QueueUrl, StringComparer.Ordinal);

            foreach (var group in groupByDestination)
            {
                SqsPreparedMessage firstMessage = null;
                var payloadSize = 0L;
                foreach (var message in group)
                {
                    firstMessage = firstMessage ?? message;

                    // Assumes the size was already calculated by the dispatcher
                    var size = message.Size;
                    payloadSize += size;

                    if (payloadSize > TransportConfiguration.MaximumMessageSize)
                    {
                        allBatches.Add(message.ToBatchRequest(currentDestinationBatches));
                        currentDestinationBatches.Clear();
                        payloadSize = size;
                    }

                    // we don't have to recheck payload size here because the support layer checks that a request can always fit 256 KB size limit
                    // we can't take MessageId because batch request ID can only contain alphanumeric characters, hyphen and underscores, message id could be overloaded
                    currentDestinationBatches.Add(Guid.NewGuid().ToString(), message);

                    var currentCount = currentDestinationBatches.Count;
                    if (currentCount != 0 && currentCount % TransportConfiguration.MaximumItemsInBatch == 0)
                    {
                        allBatches.Add(message.ToBatchRequest(currentDestinationBatches));
                        currentDestinationBatches.Clear();
                        payloadSize = 0;
                    }
                }

                if (currentDestinationBatches.Count > 0)
                {
                    allBatches.Add(firstMessage.ToBatchRequest(currentDestinationBatches));
                    currentDestinationBatches.Clear();
                }
            }

            return(allBatches);
        }
        public static BatchEntry ToBatchRequest(this SqsPreparedMessage message, Dictionary <string, SqsPreparedMessage> batchEntries)
        {
            var preparedMessagesBydId = batchEntries.ToDictionary(x => x.Key, x => x.Value);

            var batchRequestEntries = new List <SendMessageBatchRequestEntry>();

            foreach (var kvp in preparedMessagesBydId)
            {
                batchRequestEntries.Add(kvp.Value.ToBatchEntry(kvp.Key));
            }

            return(new BatchEntry
            {
                BatchRequest = new SendMessageBatchRequest(message.QueueUrl, batchRequestEntries),
                PreparedMessagesBydId = preparedMessagesBydId
            });
        }
 async Task SendMessage(SqsPreparedMessage message)
 {
     try
     {
         await sqsClient.SendMessageAsync(message.ToRequest())
         .ConfigureAwait(false);
     }
     catch (QueueDoesNotExistException e) when(message.OriginalDestination != null)
     {
         throw new QueueDoesNotExistException($"Destination '{message.OriginalDestination}' doesn't support delayed messages longer than {TimeSpan.FromSeconds(configuration.DelayedDeliveryQueueDelayTime)}. To enable support for longer delays, call '.UseTransport<SqsTransport>().UnrestrictedDurationDelayedDelivery()' on the '{message.OriginalDestination}' endpoint.", e);
     }
     catch (Exception ex)
     {
         Logger.Error($"Error while sending message, with MessageId '{message.MessageId}', to '{message.Destination}'", ex);
         throw;
     }
 }
        async Task ApplyUnicastOperationMappingIfNecessary(UnicastTransportOperation transportOperation, SqsPreparedMessage sqsPreparedMessage, long delaySeconds, string messageId)
        {
            if (transportOperation == null || sqsPreparedMessage == null)
            {
                return;
            }

            var delayLongerThanConfiguredDelayedDeliveryQueueDelayTime = configuration.IsDelayedDeliveryEnabled && delaySeconds > configuration.DelayedDeliveryQueueDelayTime;

            if (delayLongerThanConfiguredDelayedDeliveryQueueDelayTime)
            {
                sqsPreparedMessage.OriginalDestination = transportOperation.Destination;
                sqsPreparedMessage.Destination         = $"{transportOperation.Destination}{TransportConfiguration.DelayedDeliveryQueueSuffix}";
                sqsPreparedMessage.QueueUrl            = await queueCache.GetQueueUrl(sqsPreparedMessage.Destination)
                                                         .ConfigureAwait(false);

                sqsPreparedMessage.MessageDeduplicationId = messageId;
                sqsPreparedMessage.MessageGroupId         = messageId;

                sqsPreparedMessage.MessageAttributes[TransportHeaders.DelaySeconds] = new MessageAttributeValue
                {
                    StringValue = delaySeconds.ToString(),
                    DataType    = "String"
                };
            }
            else
            {
                sqsPreparedMessage.Destination = transportOperation.Destination;
                sqsPreparedMessage.QueueUrl    = await queueCache.GetQueueUrl(sqsPreparedMessage.Destination)
                                                 .ConfigureAwait(false);

                if (delaySeconds > 0)
                {
                    sqsPreparedMessage.DelaySeconds = Convert.ToInt32(delaySeconds);
                }
            }
        }
        async Task SendMessageForBatch(SqsPreparedMessage message, int batchNumber, int totalBatches)
        {
            await SendMessage(message).ConfigureAwait(false);

            Logger.Info($"Retried message with MessageId {message.MessageId} that failed in batch '{batchNumber}/{totalBatches}'.");
        }