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); }
/// <summary> /// Transforms all the <see cref="QueueAddress" /> in <see cref="headersToApplyNameMapping" /> to use logical names. /// </summary> internal void ApplyMappingToAliases(Dictionary <string, string> headers) { foreach (var header in headersToApplyNameMapping) { if (headers.TryGetValue(header, out var headerValue)) { var address = QueueAddress.Parse(headerValue); // no mapping if address is default if (address.IsAccountDefault) { continue; } // try map as connection string if (TryMap(new ConnectionString(address.StorageAccount), out var alias)) { headers[header] = new QueueAddress(address.QueueName, alias).ToString(); } else { if (useLogicalQueueAddresses) { // it must be a logical name, try to find it, otherwise throw if (aliasToAccountInfoMap.ContainsKey(address.StorageAccount) == false) { throw new Exception($"No account was mapped under following name '{address.StorageAccount}'. Please map it using .AccountRouting().AddAccount() method."); } } } } } }
/// <summary> /// Transforms all the <see cref="QueueAddress" /> in <see cref="headersToApplyNameMapping" /> to connection string /// values to maintain backward compatibility. /// </summary> internal void ApplyMappingOnOutgoingHeaders(Dictionary <string, string> headers, QueueAddress destinationQueue) { foreach (var header in headersToApplyNameMapping) { if (headers.TryGetValue(header, out var headerValue)) { var address = QueueAddress.Parse(headerValue); var isFullyQualifiedAddress = address.IsAccountDefault == false; if (isFullyQualifiedAddress) { continue; } if (useLogicalQueueAddresses) { var sendingToAnotherAccount = destinationQueue.IsAccountDefault == false; if (sendingToAnotherAccount && address.IsAccountDefault) { headers[header] = new QueueAddress(address.QueueName, defaultConnectionStringAlias).ToString(); } } else { var connectionString = Map(address); headers[header] = new QueueAddress(address.QueueName, connectionString.Value).ToString(); } } } }
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); }
/// <summary> /// Transforms reply-to header to connection string values to maintain backward compatibility. /// </summary> internal void ApplyMappingOnOutgoingHeaders(Dictionary <string, string> headers, QueueAddress destinationQueue) { if (headers.TryGetValue(Headers.ReplyToAddress, out var headerValue)) { var address = QueueAddress.Parse(headerValue); if (address.HasNoAlias == false) { return; } var destinationHasAlias = destinationQueue.HasNoAlias == false; if (destinationHasAlias && address.HasNoAlias) { headers[Headers.ReplyToAddress] = new QueueAddress(address.QueueName, defaultConnectionStringAlias).ToString(); } } }