Esempio n. 1
0
        public async Task Send(UnicastTransportOperation operation, CancellationToken cancellationToken)
        {
            var dispatchDecision = await shouldSend(operation, cancellationToken).ConfigureAwait(false);

            if (dispatchDecision == false)
            {
                return;
            }

            // The destination might be in a queue@destination format
            var destination = operation.Destination;

            var queue            = QueueAddress.Parse(destination);
            var connectionString = addressing.Map(queue);

            var sendClient = createQueueClients.Create(connectionString);
            var q          = addressGenerator.GetQueueName(queue.QueueName);
            var sendQueue  = sendClient.GetQueueReference(q);

            if (!await ExistsAsync(sendQueue).ConfigureAwait(false))
            {
                throw new QueueNotFoundException
                      {
                          Queue = queue.ToString()
                      };
            }

            var toBeReceived     = operation.GetTimeToBeReceived();
            var timeToBeReceived = toBeReceived.HasValue && toBeReceived.Value < TimeSpan.MaxValue ? toBeReceived : null;

            if (timeToBeReceived != null && timeToBeReceived.Value == TimeSpan.Zero)
            {
                var messageType = operation.Message.Headers[Headers.EnclosedMessageTypes].Split(',').First();
                logger.WarnFormat("TimeToBeReceived is set to zero for message of type '{0}'. Cannot send operation.", messageType);
                return;
            }

            // user explicitly specified TimeToBeReceived that is not TimeSpan.MaxValue - fail
            if (timeToBeReceived != null && timeToBeReceived.Value > CloudQueueMessageMaxTimeToLive && timeToBeReceived != TimeSpan.MaxValue)
            {
                var messageType = operation.Message.Headers[Headers.EnclosedMessageTypes].Split(',').First();
                throw new InvalidOperationException($"TimeToBeReceived is set to more than 30 days for message type '{messageType}'.");
            }

            if (timeToBeReceived.HasValue)
            {
                var seconds = Convert.ToInt64(Math.Ceiling(timeToBeReceived.Value.TotalSeconds));

                if (seconds <= 0)
                {
                    throw new Exception($"Message cannot be sent with a provided delay of {timeToBeReceived.Value.TotalMilliseconds} ms.");
                }

                timeToBeReceived = TimeSpan.FromSeconds(seconds);
            }

            var wrapper = BuildMessageWrapper(operation, queue);

            await Send(wrapper, sendQueue, timeToBeReceived ?? CloudQueueMessageMaxTimeToLive).ConfigureAwait(false);
        }
        async Task Dispatch(UnicastTransportOperation unicastMessage)
        {
            var sqsTransportMessage = new TransportMessage(unicastMessage.Message, unicastMessage.DeliveryConstraints);
            var serializedMessage   = JsonConvert.SerializeObject(sqsTransportMessage);

            if (serializedMessage.Length > 256 * 1024)
            {
                if (string.IsNullOrEmpty(configuration.S3BucketForLargeMessages))
                {
                    throw new Exception("Cannot send large message because no S3 bucket was configured. Add an S3 bucket name to your configuration.");
                }

                var key = $"{configuration.S3KeyPrefix}/{unicastMessage.Message.MessageId}";

                using (var bodyStream = new MemoryStream(unicastMessage.Message.Body))
                {
                    await s3Client.PutObjectAsync(new PutObjectRequest
                    {
                        BucketName  = configuration.S3BucketForLargeMessages,
                        InputStream = bodyStream,
                        Key         = key
                    }).ConfigureAwait(false);
                }

                sqsTransportMessage.S3BodyKey = key;
                sqsTransportMessage.Body      = string.Empty;
                serializedMessage             = JsonConvert.SerializeObject(sqsTransportMessage);
            }

            await SendMessage(serializedMessage, unicastMessage.Destination, unicastMessage.DeliveryConstraints)
            .ConfigureAwait(false);
        }
        Task Dispatch(SqlConnection connection, SqlTransaction transaction, UnicastTransportOperation operation, CancellationToken cancellationToken)
        {
            var discardIfNotReceivedBefore = operation.Properties.DiscardIfNotReceivedBefore;
            var doNotDeliverBefore         = operation.Properties.DoNotDeliverBefore;

            if (doNotDeliverBefore != null)
            {
                if (discardIfNotReceivedBefore != null && discardIfNotReceivedBefore.MaxTime < TimeSpan.MaxValue)
                {
                    throw new Exception("Delayed delivery of messages with TimeToBeReceived set is not supported. Remove the TimeToBeReceived attribute to delay messages of this type.");
                }

                return(delayedMessageTable.Store(operation.Message, doNotDeliverBefore.At - DateTimeOffset.UtcNow, operation.Destination, connection, transaction, cancellationToken));
            }

            var delayDeliveryWith = operation.Properties.DelayDeliveryWith;

            if (delayDeliveryWith != null)
            {
                if (discardIfNotReceivedBefore != null && discardIfNotReceivedBefore.MaxTime < TimeSpan.MaxValue)
                {
                    throw new Exception("Delayed delivery of messages with TimeToBeReceived set is not supported. Remove the TimeToBeReceived attribute to delay messages of this type.");
                }

                return(delayedMessageTable.Store(operation.Message, delayDeliveryWith.Delay, operation.Destination, connection, transaction, cancellationToken));
            }

            var queue = tableBasedQueueCache.Get(operation.Destination);

            return(queue.Send(operation.Message, discardIfNotReceivedBefore?.MaxTime ?? TimeSpan.MaxValue, connection, transaction, cancellationToken));
        }
Esempio n. 4
0
        Task SendMessage(UnicastTransportOperation transportOperation)
        {
            Logger.Debug("Send to " + transportOperation.Destination);

            var toBeReceived     = transportOperation.GetTimeToBeReceived();
            var timeToBeReceived = toBeReceived.HasValue && toBeReceived.Value < TimeSpan.MaxValue
                ? toBeReceived
                : null;

            if (timeToBeReceived != null && timeToBeReceived.Value == TimeSpan.Zero)
            {
                var messageType = transportOperation.Message.Headers[Headers.EnclosedMessageTypes].Split(',').First();
                Logger.WarnFormat("TimeToBeReceived is set to zero for message of type '{0}'. Cannot send operation.",
                                  messageType);
                return(Task.FromResult(0));
            }

            // TimeToBeReceived was not specified on message - go for maximum set by SDK
            if (timeToBeReceived == TimeSpan.MaxValue)
            {
                timeToBeReceived = null;
            }

            var messageWrapper = BuildMessageWrapper(transportOperation, toBeReceived, transportOperation.Destination);

            var topic = producerFactory.GetProducer().Topic(transportOperation.Destination);

            var messageStream = new MemoryStream();

            KafkaTransportInfrastructure.GetSerializer().Serialize(messageWrapper, messageStream);

            return(topic.Produce(messageStream.ToArray()));
        }
Esempio n. 5
0
        Task Dispatch(SqlConnection connection, SqlTransaction transaction, UnicastTransportOperation operation)
        {
            TryGetConstraint(operation, out DiscardIfNotReceivedBefore discardIfNotReceivedBefore);
            if (TryGetConstraint(operation, out DoNotDeliverBefore doNotDeliverBefore))
            {
                if (discardIfNotReceivedBefore != null && discardIfNotReceivedBefore.MaxTime < TimeSpan.MaxValue)
                {
                    throw new Exception("Delayed delivery of messages with TimeToBeReceived set is not supported. Remove the TimeToBeReceived attribute to delay messages of this type.");
                }

                return(delayedMessageTable.Store(operation.Message, doNotDeliverBefore.At - DateTime.UtcNow, operation.Destination, connection, transaction));
            }
            if (TryGetConstraint(operation, out DelayDeliveryWith delayDeliveryWith))
            {
                if (discardIfNotReceivedBefore != null && discardIfNotReceivedBefore.MaxTime < TimeSpan.MaxValue)
                {
                    throw new Exception("Delayed delivery of messages with TimeToBeReceived set is not supported. Remove the TimeToBeReceived attribute to delay messages of this type.");
                }

                return(delayedMessageTable.Store(operation.Message, delayDeliveryWith.Delay, operation.Destination, connection, transaction));
            }

            var queue = tableBasedQueueCache.Get(operation.Destination);

            return(queue.Send(operation.Message, discardIfNotReceivedBefore?.MaxTime ?? TimeSpan.MaxValue, connection, transaction));
        }
Esempio n. 6
0
        public async Task <bool> ShouldDispatch(UnicastTransportOperation operation, CancellationToken cancellationToken)
        {
            var constraints = operation.DeliveryConstraints;
            var delay       = GetVisibilityDelay(constraints);

            if (delay != null)
            {
                if (FirstOrDefault <DiscardIfNotReceivedBefore>(constraints) != null)
                {
                    throw new Exception($"Postponed delivery of messages with TimeToBeReceived set is not supported. Remove the TimeToBeReceived attribute to postpone messages of type '{operation.Message.Headers[Headers.EnclosedMessageTypes]}'.");
                }

                await ScheduleAt(operation, UtcNow + delay.Value, cancellationToken).ConfigureAwait(false);

                return(false);
            }

            if (TryProcessDelayedRetry(operation, out var operationToSchedule, out var scheduleDate))
            {
                await ScheduleAt(operationToSchedule, scheduleDate, cancellationToken).ConfigureAwait(false);

                return(false);
            }

            return(true);
        }
Esempio n. 7
0
        static DispatchBehavior GetDueTime(UnicastTransportOperation operation)
        {
            DoNotDeliverBefore doNotDeliverBefore;
            DelayDeliveryWith  delayDeliveryWith;

            if (TryGetConstraint(operation, out doNotDeliverBefore))
            {
                return(DispatchBehavior.Deferred(doNotDeliverBefore.At, operation.Destination));
            }
            if (TryGetConstraint(operation, out delayDeliveryWith))
            {
                return(DispatchBehavior.Deferred(DateTime.UtcNow + delayDeliveryWith.Delay, operation.Destination));
            }
            string expireString;
            var    headers = operation.Message.Headers;

            if (headers.TryGetValue(TimeoutManagerHeaders.Expire, out expireString))
            {
                var expirationTime = DateTimeExtensions.ToUtcDateTime(expireString);
                var destination    = headers[TimeoutManagerHeaders.RouteExpiredTimeoutTo];

                headers.Remove(TimeoutManagerHeaders.RouteExpiredTimeoutTo);
                headers.Remove(TimeoutManagerHeaders.Expire);

                return(DispatchBehavior.Deferred(expirationTime, destination));
            }
            return(DispatchBehavior.Immediately());
        }
 public void SetOperation(UnicastTransportOperation operation)
 {
     Destination = operation.Destination;
     Body        = operation.Message.Body;
     MessageId   = operation.Message.MessageId;
     Headers     = Serialize(operation.Message.Headers);
 }
Esempio n. 9
0
        public async Task Send(UnicastTransportOperation operation, CancellationToken cancellationToken = default)
        {
            if (logger.IsDebugEnabled)
            {
                logger.DebugFormat("Sending message (ID: '{0}') to {1}", operation.Message.MessageId, operation.Destination);
            }

            if (NativeDelayDeliveryPersistence.IsDelayedMessage(operation, out var dueDate))
            {
                await nativeDelayDeliveryPersistence.ScheduleAt(operation, dueDate, cancellationToken).ConfigureAwait(false);
                return;
            }

            // The destination might be in a queue@destination format
            var destination = operation.Destination;

            var messageIntent = operation.GetMessageIntent();
            var queueAddress = QueueAddress.Parse(destination, messageIntent == MessageIntentEnum.Reply);
            var queueServiceClient = addressing.Map(queueAddress, messageIntent);

            var queueName = addressGenerator.GetQueueName(queueAddress.QueueName);
            var sendQueue = queueServiceClient.GetQueueClient(queueName);

            if (!await ExistsAsync(sendQueue, cancellationToken).ConfigureAwait(false))
            {
                throw new QueueNotFoundException(queueAddress.ToString(), $"Destination queue '{queueAddress}' does not exist. This queue may have to be created manually.", null);
            }

            var toBeReceived = operation.Properties.DiscardIfNotReceivedBefore;
            var timeToBeReceived = toBeReceived != null && toBeReceived.MaxTime < TimeSpan.MaxValue ? toBeReceived.MaxTime : (TimeSpan?)null;

            if (timeToBeReceived.HasValue)
            {
                if (timeToBeReceived.Value == TimeSpan.Zero)
                {
                    var messageType = operation.Message.Headers[Headers.EnclosedMessageTypes].Split(',').First();
                    logger.WarnFormat("TimeToBeReceived is set to zero for message of type '{0}'. Cannot send operation.", messageType);
                    return;
                }

                // user explicitly specified TimeToBeReceived that is not TimeSpan.MaxValue - fail
                if (timeToBeReceived.Value > CloudQueueMessageMaxTimeToLive && timeToBeReceived.Value != TimeSpan.MaxValue)
                {
                    var messageType = operation.Message.Headers[Headers.EnclosedMessageTypes].Split(',').First();
                    throw new InvalidOperationException($"TimeToBeReceived is set to more than 30 days for message type '{messageType}'.");
                }

                var seconds = Convert.ToInt64(Math.Ceiling(timeToBeReceived.Value.TotalSeconds));
                if (seconds <= 0)
                {
                    throw new Exception($"Message cannot be sent with a provided delay of {timeToBeReceived.Value.TotalMilliseconds} ms.");
                }

                timeToBeReceived = TimeSpan.FromSeconds(seconds);
            }

            var wrapper = BuildMessageWrapper(operation, queueAddress);
            await Send(wrapper, sendQueue, timeToBeReceived ?? CloudQueueMessageMaxTimeToLive, cancellationToken).ConfigureAwait(false);
        }
Esempio n. 10
0
        async Task Dispatch(UnicastTransportOperation transportOperation)
        {
            var message = await PrepareMessage(transportOperation)
                          .ConfigureAwait(false);

            await SendMessage(message)
            .ConfigureAwait(false);
        }
        public Func <SqlConnection, SqlTransaction, Task> Get(UnicastTransportOperation operation)
        {
            TryGetConstraint(operation, out DiscardIfNotReceivedBefore discardIfNotReceivedBefore);

            var address = addressTranslator.Parse(operation.Destination);
            var key     = Tuple.Create(address.QualifiedTableName, address.Address);
            var queue   = cache.GetOrAdd(key, x => new TableBasedQueue(x.Item1, x.Item2));

            return((conn, trans) => queue.Send(operation.Message, discardIfNotReceivedBefore?.MaxTime ?? TimeSpan.MaxValue, conn, trans));
        }
Esempio n. 12
0
        public void Should_not_share_constraints_when_not_provided()
        {
            var transportOperation       = new UnicastTransportOperation(new OutgoingMessage(Guid.NewGuid().ToString(), new Dictionary <string, string>(), new byte[0]), "destination", new DispatchProperties());
            var secondTransportOperation = new UnicastTransportOperation(new OutgoingMessage(Guid.NewGuid().ToString(), new Dictionary <string, string>(), new byte[0]), "destination2", new DispatchProperties());

            transportOperation.Properties.DiscardIfNotReceivedBefore = new DiscardIfNotReceivedBefore(TimeSpan.FromDays(1));

            Assert.IsEmpty(secondTransportOperation.Properties);
            Assert.IsNotEmpty(transportOperation.Properties);
        }
        Task SendMessage(UnicastTransportOperation transportOperation, ConfirmsAwareChannel channel, CancellationToken cancellationToken)
        {
            var message = transportOperation.Message;

            var properties = channel.CreateBasicProperties();

            properties.Fill(message, transportOperation.Properties);

            return(channel.SendMessage(transportOperation.Destination, message, properties, cancellationToken));
        }
        Task SendMessage(UnicastTransportOperation transportOperation, ConfirmsAwareChannel channel)
        {
            var message = transportOperation.Message;

            var properties = channel.CreateBasicProperties();

            properties.Fill(message, transportOperation.DeliveryConstraints, channel.SupportsDelayedDelivery, out var destination);

            return(channel.SendMessage(destination ?? transportOperation.Destination, message, properties));
        }
Esempio n. 15
0
        Task ScheduleAt(UnicastTransportOperation operation, DateTimeOffset date, CancellationToken cancellationToken)
        {
            var delayedMessageEntity = new DelayedMessageEntity
            {
                PartitionKey = DelayedMessageEntity.GetPartitionKey(date),
                RowKey       = $"{DelayedMessageEntity.GetRawRowKeyPrefix(date)}_{Guid.NewGuid():N}",
            };

            delayedMessageEntity.SetOperation(operation);
            return(delayedMessagesTable.ExecuteAsync(TableOperation.Insert(delayedMessageEntity), null, null, cancellationToken));
        }
        async Task Dispatch(UnicastTransportOperation transportOperation)
        {
            var delayDeliveryWith  = transportOperation.DeliveryConstraints.OfType <DelayDeliveryWith>().SingleOrDefault();
            var doNotDeliverBefore = transportOperation.DeliveryConstraints.OfType <DoNotDeliverBefore>().SingleOrDefault();

            long delaySeconds = 0;

            if (delayDeliveryWith != null)
            {
                delaySeconds = Convert.ToInt64(Math.Ceiling(delayDeliveryWith.Delay.TotalSeconds));
            }
            else if (doNotDeliverBefore != null)
            {
                delaySeconds = Convert.ToInt64(Math.Ceiling((doNotDeliverBefore.At - DateTime.UtcNow).TotalSeconds));
            }

            if (!configuration.IsDelayedDeliveryEnabled && delaySeconds > TransportConfiguration.AwsMaximumQueueDelayTime)
            {
                throw new NotSupportedException($"To send messages with a delay time greater than '{TimeSpan.FromSeconds(TransportConfiguration.AwsMaximumQueueDelayTime)}', call '.UseTransport<SqsTransport>().UnrestrictedDelayedDelivery()'.");
            }

            var sqsTransportMessage = new TransportMessage(transportOperation.Message, transportOperation.DeliveryConstraints);

            var serializedMessage = JsonConvert.SerializeObject(sqsTransportMessage, jsonSerializerSettings);

            if (serializedMessage.Length > 256 * 1024)
            {
                if (string.IsNullOrEmpty(configuration.S3BucketForLargeMessages))
                {
                    throw new Exception("Cannot send large message because no S3 bucket was configured. Add an S3 bucket name to your configuration.");
                }

                var key = $"{configuration.S3KeyPrefix}/{transportOperation.Message.MessageId}";

                using (var bodyStream = new MemoryStream(transportOperation.Message.Body))
                {
                    await s3Client.PutObjectAsync(new PutObjectRequest
                    {
                        BucketName  = configuration.S3BucketForLargeMessages,
                        InputStream = bodyStream,
                        Key         = key
                    }).ConfigureAwait(false);
                }

                sqsTransportMessage.S3BodyKey = key;
                sqsTransportMessage.Body      = string.Empty;
                serializedMessage             = JsonConvert.SerializeObject(sqsTransportMessage, jsonSerializerSettings);
            }

            await SendMessage(serializedMessage, transportOperation.Destination, delaySeconds, transportOperation.Message.MessageId)
            .ConfigureAwait(false);
        }
Esempio n. 17
0
        Task SendMessage(UnicastTransportOperation transportOperation, ConfirmsAwareChannel channel, RabbitMQMessagePriority priority)
        {
            var message = transportOperation.Message;

            var properties = channel.CreateBasicProperties();

            properties.Fill(message, transportOperation.DeliveryConstraints, out var destination);
            if (priority != null)
            {
                properties.Priority = priority.Priority;
            }
            return(channel.SendMessage(destination ?? transportOperation.Destination, message, properties));
        }
 private void DispatchUnicastMessage(UnicastTransportOperation unicastTransportOperation)
 {
     try
     {
         MessageSent?.Invoke(
             unicastTransportOperation,
             unicastTransportOperation.Destination);
     }
     catch (Exception e)
     {
         Console.WriteLine(e);
     }
 }
Esempio n. 19
0
        void ExecuteTransportOperation(TransportTransaction transaction, UnicastTransportOperation transportOperation)
        {
            bool isDelayedMessage = transportOperation.Properties.DelayDeliveryWith != null || transportOperation.Properties.DoNotDeliverBefore != null;

            if (isDelayedMessage)
            {
                SendToDelayedDeliveryQueue(transaction, transportOperation);
            }
            else
            {
                SendToDestination(transaction, transportOperation);
            }
        }
        // ReSharper disable once SuggestBaseTypeForParameter
        async Task Dispatch(UnicastTransportOperation transportOperation, HashSet <string> messageIdsOfMulticastedEvents)
        {
            var message = await PrepareMessage <SqsPreparedMessage>(transportOperation, messageIdsOfMulticastedEvents)
                          .ConfigureAwait(false);

            if (message == null)
            {
                return;
            }

            await SendMessage(message)
            .ConfigureAwait(false);
        }
Esempio n. 21
0
        public Task ScheduleAt(UnicastTransportOperation operation, DateTimeOffset date, CancellationToken cancellationToken = default)
        {
            if (!enabled)
            {
                throw new Exception("Native delayed deliveries are not enabled.");
            }

            var delayedMessageEntity = new DelayedMessageEntity
            {
                PartitionKey = DelayedMessageEntity.GetPartitionKey(date),
                RowKey       = $"{DelayedMessageEntity.GetRawRowKeyPrefix(date)}_{Guid.NewGuid():N}",
            };

            delayedMessageEntity.SetOperation(operation);
            return(delayedMessageStorageTable.ExecuteAsync(TableOperation.Insert(delayedMessageEntity), null, null, cancellationToken));
        }
        public Func <SqlConnection, SqlTransaction, Task> Get(UnicastTransportOperation operation)
        {
            var behavior = GetDueTime(operation);

            TryGetConstraint(operation, out DiscardIfNotReceivedBefore discardIfNotReceivedBefore);
            if (behavior.Defer)
            {
                // align with TimeoutManager behavior
                if (discardIfNotReceivedBefore != null && discardIfNotReceivedBefore.MaxTime < TimeSpan.MaxValue)
                {
                    throw new Exception("Delayed delivery of messages with TimeToBeReceived set is not supported. Remove the TimeToBeReceived attribute to delay messages of this type.");
                }

                return((conn, trans) => delayedMessageTable.Store(operation.Message, behavior.DueTime, behavior.Destination, conn, trans));
            }
            return(immediateDeliveryQueueOperationsReader.Get(operation));
        }
Esempio n. 23
0
    async Task SendMessage(UnicastTransportOperation transportOperation)
    {
        var publisher = await PublisherClient.CreateAsync();

        var message          = transportOperation.Message;
        var transportMessage = new PubsubMessage
        {
            MessageId = message.MessageId,
            Data      = ByteString.CopyFrom(message.Body)
        };

        transportMessage.Attributes.Add(message.Headers);
        await publisher.PublishAsync(new TopicName(projectId, transportOperation.Destination), new[]
        {
            transportMessage
        })
        .ConfigureAwait(false);
    }
Esempio n. 24
0
        public static bool IsDelayedMessage(UnicastTransportOperation operation, out DateTimeOffset dueDate)
        {
            var delay = GetDeliveryDelay(operation.Properties);

            if (delay != null)
            {
                if (operation.Properties.DiscardIfNotReceivedBefore != null)
                {
                    throw new Exception($"Delayed delivery of messages with TimeToBeReceived set is not supported. Remove the TimeToBeReceived attribute to postpone messages of type '{operation.Message.Headers[Headers.EnclosedMessageTypes]}'.");
                }

                dueDate = DateTimeOffset.UtcNow + delay.Value;

                return(true);
            }

            dueDate = DateTimeOffset.MinValue;
            return(false);
        }
        private void DispatcherOnMessageSent(UnicastTransportOperation operation, string destination)
        {
            List <MessagePump> receivers = new List <MessagePump>();

            foreach (var infrastructure in infrastructures)
            {
                foreach (var pump in infrastructure.messagePumps)
                {
                    if (pump.inputQueue == destination)
                    {
                        receivers.Add(pump);
                    }
                }
            }

            Task.Run(() => receivers
                     .FirstOrDefault()?
                     .Push(operation.Message.Body, operation.Message.MessageId, operation.Message.Headers));
        }
        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);
                }
            }
        }
Esempio n. 27
0
        public async Task <bool> ShouldDispatch(UnicastTransportOperation operation, CancellationToken cancellationToken)
        {
            var constraints = operation.DeliveryConstraints;
            var delay       = GetVisibilityDelay(constraints);

            if (delay != null)
            {
                if (delayedDeliveryDisabled)
                {
                    throw new Exception("Cannot delay delivery of messages when delayed delivery has been disabled. Remove the 'endpointConfiguration.UseTransport<AzureStorageQueues>.DelayedDelivery().DisableDelayedDelivery()' configuration to re-enable delayed delivery.");
                }

                if (FirstOrDefault <DiscardIfNotReceivedBefore>(constraints) != null)
                {
                    throw new Exception($"Postponed delivery of messages with TimeToBeReceived set is not supported. Remove the TimeToBeReceived attribute to postpone messages of type '{operation.Message.Headers[Headers.EnclosedMessageTypes]}'.");
                }

                await ScheduleAt(operation, UtcNow + delay.Value, cancellationToken).ConfigureAwait(false);

                return(false);
            }

            return(true);
        }
Esempio n. 28
0
        static bool TryProcessDelayedRetry(IOutgoingTransportOperation operation, out UnicastTransportOperation operationToSchedule, out DateTimeOffset scheduleDate)
        {
            var messageHeaders = operation.Message.Headers;

            if (messageHeaders.TryGetValue(TimeoutManagerHeaders.Expire, out var expire))
            {
                var expiration = DateTimeExtensions.ToUtcDateTime(expire);

                var destination = messageHeaders[TimeoutManagerHeaders.RouteExpiredTimeoutTo];

                messageHeaders.Remove(TimeoutManagerHeaders.Expire);
                messageHeaders.Remove(TimeoutManagerHeaders.RouteExpiredTimeoutTo);

                operationToSchedule = new UnicastTransportOperation(operation.Message, destination, operation.RequiredDispatchConsistency, operation.DeliveryConstraints);

                scheduleDate = expiration;

                return(true);
            }

            operationToSchedule = null;
            scheduleDate        = default(DateTimeOffset);
            return(false);
        }
Esempio n. 29
0
        public async Task RawSending()
        {
            IDispatchMessages dispatcher = null;

            #region DispatcherRawSending

            var headers         = new Dictionary <string, string>();
            var outgoingMessage = new OutgoingMessage("MessageId", headers, new byte[]
            {
            });
            var constraints = new[]
            {
                new NonDurableDelivery()
            };
            UnicastAddressTag         address                             = new UnicastAddressTag("Destination");
            TransportOperation        transportOperation                  = new TransportOperation(outgoingMessage, address, DispatchConsistency.Default, constraints);
            UnicastTransportOperation unicastTransportOperation           = new UnicastTransportOperation(outgoingMessage, "destination");
            IEnumerable <MulticastTransportOperation> multicastOperations = Enumerable.Empty <MulticastTransportOperation>();
            UnicastTransportOperation[] unicastOperations                 = { unicastTransportOperation };
            TransportOperations         operations                        = new TransportOperations(multicastOperations, unicastOperations);
            await dispatcher.Dispatch(operations, new ContextBag());

            #endregion
        }
Esempio n. 30
0
        public async Task RawSending()
        {
            IDispatchMessages dispatcher = null;

            #region DispatcherRawSending

            var headers = new Dictionary<string, string>();
            var outgoingMessage = new OutgoingMessage("MessageId", headers, new byte[]
            {
            });
            var constraints = new[]
            {
                new NonDurableDelivery()
            };
            UnicastAddressTag address = new UnicastAddressTag("Destination");
            TransportOperation transportOperation = new TransportOperation(outgoingMessage, address, DispatchConsistency.Default, constraints);
            UnicastTransportOperation unicastTransportOperation = new UnicastTransportOperation(outgoingMessage, "destination");
            IEnumerable<MulticastTransportOperation> multicastOperations = Enumerable.Empty<MulticastTransportOperation>();
            UnicastTransportOperation[] unicastOperations = {unicastTransportOperation};
            TransportOperations operations = new TransportOperations(multicastOperations, unicastOperations);
            await dispatcher.Dispatch(operations, new ContextBag());

            #endregion
        }
Esempio n. 31
0
        async Task <PreparedMessage> PrepareMessage(UnicastTransportOperation transportOperation)
        {
            var delayDeliveryWith  = transportOperation.DeliveryConstraints.OfType <DelayDeliveryWith>().SingleOrDefault();
            var doNotDeliverBefore = transportOperation.DeliveryConstraints.OfType <DoNotDeliverBefore>().SingleOrDefault();

            long delaySeconds = 0;

            if (delayDeliveryWith != null)
            {
                delaySeconds = Convert.ToInt64(Math.Ceiling(delayDeliveryWith.Delay.TotalSeconds));
            }
            else if (doNotDeliverBefore != null)
            {
                delaySeconds = Convert.ToInt64(Math.Ceiling((doNotDeliverBefore.At - DateTime.UtcNow).TotalSeconds));
            }

            if (!configuration.IsDelayedDeliveryEnabled && delaySeconds > TransportConfiguration.AwsMaximumQueueDelayTime)
            {
                throw new NotSupportedException($"To send messages with a delay time greater than '{TimeSpan.FromSeconds(TransportConfiguration.AwsMaximumQueueDelayTime)}', call '.UseTransport<SqsTransport>().UnrestrictedDelayedDelivery()'.");
            }

            var sqsTransportMessage = new TransportMessage(transportOperation.Message, transportOperation.DeliveryConstraints);

            var serializedMessage = SimpleJson.SerializeObject(sqsTransportMessage, serializerStrategy);

            var messageId = transportOperation.Message.MessageId;

            if (serializedMessage.Length > TransportConfiguration.MaximumMessageSize)
            {
                if (string.IsNullOrEmpty(configuration.S3BucketForLargeMessages))
                {
                    throw new Exception("Cannot send large message because no S3 bucket was configured. Add an S3 bucket name to your configuration.");
                }

                var key = $"{configuration.S3KeyPrefix}/{messageId}";

                using (var bodyStream = new MemoryStream(transportOperation.Message.Body))
                {
                    var request = new PutObjectRequest
                    {
                        BucketName  = configuration.S3BucketForLargeMessages,
                        InputStream = bodyStream,
                        Key         = key
                    };

                    if (configuration.S3EncryptionMethod != null)
                    {
                        request.ServerSideEncryptionMethod = configuration.S3EncryptionMethod;
                    }

                    await s3Client.PutObjectAsync(request).ConfigureAwait(false);
                }

                sqsTransportMessage.S3BodyKey = key;
                sqsTransportMessage.Body      = string.Empty;
                serializedMessage             = SimpleJson.SerializeObject(sqsTransportMessage, serializerStrategy);
            }

            var preparedMessage = new PreparedMessage();

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

            if (delayLongerThanConfiguredDelayedDeliveryQueueDelayTime)
            {
                preparedMessage.OriginalDestination = transportOperation.Destination;
                preparedMessage.Destination         = $"{transportOperation.Destination}{TransportConfiguration.DelayedDeliveryQueueSuffix}";
                preparedMessage.QueueUrl            = await queueUrlCache.GetQueueUrl(QueueNameHelper.GetSqsQueueName(preparedMessage.Destination, configuration))
                                                      .ConfigureAwait(false);

                preparedMessage.MessageDeduplicationId = messageId;
                preparedMessage.MessageGroupId         = messageId;

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

                preparedMessage.MessageAttributes[Headers.MessageId] = new MessageAttributeValue
                {
                    StringValue = messageId,
                    DataType    = "String"
                };

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

            preparedMessage.Body      = serializedMessage;
            preparedMessage.MessageId = messageId;

            return(preparedMessage);
        }
        void ExecuteTransportOperation(TransportTransaction transaction, UnicastTransportOperation transportOperation)
        {
            var message = transportOperation.Message;

            var destination = transportOperation.Destination;
            var destinationAddress = MsmqAddress.Parse(destination);

            if (IsCombiningTimeToBeReceivedWithTransactions(
                transaction,
                transportOperation.RequiredDispatchConsistency,
                transportOperation.DeliveryConstraints))
            {
                throw new Exception($"Failed to send message to address: {destinationAddress.Queue}@{destinationAddress.Machine}. Sending messages with a custom TimeToBeReceived is not supported on transactional MSMQ.");
            }

            try
            {
                using (var q = new MessageQueue(destinationAddress.FullPath, false, settings.UseConnectionCache, QueueAccessMode.Send))
                {
                    using (var toSend = MsmqUtilities.Convert(message, transportOperation.DeliveryConstraints))
                    {
                        toSend.UseDeadLetterQueue = settings.UseDeadLetterQueue;
                        toSend.UseJournalQueue = settings.UseJournalQueue;
                        toSend.TimeToReachQueue = settings.TimeToReachQueue;

                        string replyToAddress;

                        if (message.Headers.TryGetValue(Headers.ReplyToAddress, out replyToAddress))
                        {
                            toSend.ResponseQueue = new MessageQueue(MsmqAddress.Parse(replyToAddress).FullPath);
                        }

                        var label = GetLabel(message);

                        if (transportOperation.RequiredDispatchConsistency == DispatchConsistency.Isolated)
                        {
                            q.Send(toSend, label, GetIsolatedTransactionType());
                            return;
                        }

                        MessageQueueTransaction activeTransaction;
                        if (TryGetNativeTransaction(transaction, out activeTransaction))
                        {
                            q.Send(toSend, label, activeTransaction);
                            return;
                        }

                        q.Send(toSend, label, GetTransactionTypeForSend());
                    }
                }
            }
            catch (MessageQueueException ex)
            {
                if (ex.MessageQueueErrorCode == MessageQueueErrorCode.QueueNotFound)
                {
                    var msg = destination == null
                        ? "Failed to send message. Target address is null."
                        : $"Failed to send message to address: [{destination}]";

                    throw new QueueNotFoundException(destination, msg, ex);
                }

                ThrowFailedToSendException(destination, ex);
            }
            catch (Exception ex)
            {
                ThrowFailedToSendException(destination, ex);
            }
        }