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)); }
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())); }
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)); }
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); }
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); }
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); }
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)); }
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)); }
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); }
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); } }
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); }
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)); }
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); }
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); } } }
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); }
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); }
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 }
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 }
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); } }