public SendAsyncResult(SendingAmqpLink link, AmqpMessage message, TimeSpan timeout, AsyncCallback callback, object state) : base(callback, state) { this.message = message; this.message.CompleteCallback = onSendComplete; link.SendDelivery(message); }
public IAsyncResult BeginSendMessage(AmqpMessage message, ArraySegment<byte> deliveryTag, ArraySegment<byte> txnId, TimeSpan timeout, AsyncCallback callback, object state) { Fx.Assert(message.CompleteCallback == null, "Call SendDelivery() when using a complete callback"); message.DeliveryTag = deliveryTag; message.TxnId = txnId; return new SendAsyncResult(this, message, timeout, callback, state); }
static ArraySegment<byte>[] ReadMessagePayLoad(AmqpMessage message, int payloadSize) { List<ArraySegment<byte>> buffers = new List<ArraySegment<byte>>(); bool more = true; while (more) { ArraySegment<byte>[] messageBuffers = message.GetPayload(payloadSize, out more); if (messageBuffers != null) { foreach (var segment in messageBuffers) { message.CompletePayload(segment.Count); } buffers.AddRange(messageBuffers); } } return buffers.ToArray(); }
/// <summary> /// /// </summary> /// <param name="message"></param> /// <param name="retryPolicy"></param> /// <param name="receiveLinkName"></param> /// <param name="timeout"></param> /// <param name="cancellationToken"></param> /// <returns></returns> internal async Task <long> ScheduleMessageInternal( ServiceBusMessage message, ServiceBusRetryPolicy retryPolicy, string receiveLinkName, TimeSpan timeout, CancellationToken cancellationToken = default) { var stopWatch = Stopwatch.StartNew(); using (AmqpMessage amqpMessage = AmqpMessageConverter.SBMessageToAmqpMessage(message)) { var request = AmqpRequestMessage.CreateRequest( ManagementConstants.Operations.ScheduleMessageOperation, timeout, null); if (receiveLinkName != null) { request.AmqpMessage.ApplicationProperties.Map[ManagementConstants.Request.AssociatedLinkName] = receiveLinkName; } ArraySegment <byte>[] payload = amqpMessage.GetPayload(); var buffer = new BufferListStream(payload); ArraySegment <byte> value = buffer.ReadBytes((int)buffer.Length); var entry = new AmqpMap(); { entry[ManagementConstants.Properties.Message] = value; entry[ManagementConstants.Properties.MessageId] = message.MessageId; if (!string.IsNullOrWhiteSpace(message.SessionId)) { entry[ManagementConstants.Properties.SessionId] = message.SessionId; } if (!string.IsNullOrWhiteSpace(message.PartitionKey)) { entry[ManagementConstants.Properties.PartitionKey] = message.PartitionKey; } if (!string.IsNullOrWhiteSpace(message.ViaPartitionKey)) { entry[ManagementConstants.Properties.ViaPartitionKey] = message.ViaPartitionKey; } } request.Map[ManagementConstants.Properties.Messages] = new List <AmqpMap> { entry }; RequestResponseAmqpLink link = await ManagementLink.GetOrCreateAsync( UseMinimum(ConnectionScope.SessionTimeout, timeout.CalculateRemaining(stopWatch.Elapsed))) .ConfigureAwait(false); using AmqpMessage response = await link.RequestAsync( request.AmqpMessage, timeout.CalculateRemaining(stopWatch.Elapsed)) .ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); stopWatch.Stop(); AmqpResponseMessage amqpResponseMessage = AmqpResponseMessage.CreateResponse(response); if (amqpResponseMessage.StatusCode == AmqpResponseStatusCode.OK) { var sequenceNumbers = amqpResponseMessage.GetValue <long[]>(ManagementConstants.Properties.SequenceNumbers); if (sequenceNumbers == null || sequenceNumbers.Length < 1) { throw new ServiceBusException(true, "Could not schedule message successfully."); } return(sequenceNumbers[0]); } else { throw new Exception(); //throw response.ToMessagingContractException(); } } }
public void DisposeMessage(AmqpMessage message, DeliveryState deliveryState, bool settled, bool batchable) { this.receiver.DisposeMessage(message, deliveryState, settled, batchable); }
void OnReceiveMessage(AmqpMessage message) { if (this.messageListener != null) { this.messageListener(message); } else { ReceiveAsyncResult waiter = null; lock (this.syncRoot) { if (this.waiterList != null && this.waiterList.Count > 0) { waiter = this.waiterList.First.Value; this.waiterList.RemoveFirst(); waiter.OnRemoved(); } else if (this.messageQueue != null) { this.messageQueue.Enqueue(message); } } if (waiter != null) { waiter.Signal(message, false); } } this.minTimeout = TimeSpan.Zero; }
public void RejectMessage(AmqpMessage message, Exception exception) { Rejected rejected = new Rejected(); rejected.Error = AmqpError.FromException(exception); this.DisposeMessage(message, rejected, true, false); }
void OnMessage(AmqpMessage message) { string errorCondition = null; if (message.ApplicationProperties != null && message.ApplicationProperties.Map.TryGetValue<string>("errorcondition", out errorCondition)) { this.link.DisposeMessage(message, new Rejected() { Error = new Error() { Condition = errorCondition, Description = "message was rejected" } }, true, false); } else { if (message.TxnId.Array != null) { Transaction txn = this.queue.broker.txnManager.GetTransaction(message.TxnId); txn.AddOperation(message, this.OnTxnDischarge); this.link.DisposeMessage(message, new TransactionalState() { Outcome = AmqpConstants.AcceptedOutcome }, true, message.Batchable); } else { this.queue.Enqueue(new BrokerMessage(message)); this.link.AcceptMessage(message, message.Batchable); message.Dispose(); } } }
protected override Task OnMessageReceived(AmqpMessage amqpMessage) { this.ReceivedMessages.Add(amqpMessage); return(Task.CompletedTask); }
public static AmqpResponseMessage CreateResponse(AmqpMessage response) { return(new AmqpResponseMessage(response)); }
void OnMessageReceived(AmqpMessage message) { Events.NewTokenReceived(); this.authenticationUpdateTask = this.UpdateAmqpAuthentication(message); }
static void AddSection(AmqpMessage message, SectionFlag sections) { if ((sections & SectionFlag.Header) != 0) { message.Header.Priority = 10; message.Header.Ttl = (uint)(DateTime.Parse("2011-02-01 12:00:00") - AmqpConstants.StartOfEpoch).TotalMilliseconds; } if ((sections & SectionFlag.DeliveryAnnotations) != 0) { message.DeliveryAnnotations.Map["delivery-annotation"] = "delivery annotation"; } if ((sections & SectionFlag.MessageAnnotations) != 0) { message.MessageAnnotations.Map["message-annotation"] = "message annotation"; } if ((sections & SectionFlag.Properties) != 0) { message.Properties.MessageId = "message 1"; } if ((sections & SectionFlag.ApplicationProperties) != 0) { message.ApplicationProperties.Map["message-prop"] = "message property"; } if ((sections & SectionFlag.Footer) != 0) { message.Footer.Map["footer-prop"] = "footer"; } }
static void ValidateMessage(AmqpMessage original, AmqpMessage deserialized) { Assert.Equal(original.Sections, deserialized.Sections); if ((original.Sections & SectionFlag.Header) != 0) { Assert.Equal(original.Header.Priority.Value, deserialized.Header.Priority.Value); Assert.Equal(original.Header.Ttl.Value, deserialized.Header.Ttl.Value); } if ((original.Sections & SectionFlag.DeliveryAnnotations) != 0) { Assert.Equal(original.DeliveryAnnotations.Map.Count(), deserialized.DeliveryAnnotations.Map.Count()); foreach (var pair in original.DeliveryAnnotations.Map) { Assert.Equal(original.DeliveryAnnotations.Map[pair.Key], deserialized.DeliveryAnnotations.Map[pair.Key]); } } if ((original.Sections & SectionFlag.MessageAnnotations) != 0) { Assert.Equal(original.MessageAnnotations.Map.Count(), deserialized.MessageAnnotations.Map.Count()); foreach (var pair in original.MessageAnnotations.Map) { Assert.Equal(original.MessageAnnotations.Map[pair.Key], deserialized.MessageAnnotations.Map[pair.Key]); } } if ((original.Sections & SectionFlag.Properties) != 0) { Assert.Equal(original.Properties.MessageId.ToString(), deserialized.Properties.MessageId.ToString()); } if ((original.Sections & SectionFlag.ApplicationProperties) != 0) { Assert.Equal(original.ApplicationProperties.Map.Count(), deserialized.ApplicationProperties.Map.Count()); foreach (var pair in original.ApplicationProperties.Map) { Assert.Equal(original.ApplicationProperties.Map[pair.Key], deserialized.ApplicationProperties.Map[pair.Key]); } } if ((original.Sections & SectionFlag.Footer) != 0) { Assert.Equal(original.Footer.Map.Count(), deserialized.Footer.Map.Count()); foreach (var pair in original.Footer.Map) { Assert.Equal(original.Footer.Map[pair.Key], deserialized.Footer.Map[pair.Key]); } } if ((original.Sections & SectionFlag.Data) != 0) { try { Assert.Equal(original.DataBody.Count(), deserialized.DataBody.Count()); using (IEnumerator<Data> enumerator1 = original.DataBody.GetEnumerator()) using (IEnumerator<Data> enumerator2 = deserialized.DataBody.GetEnumerator()) { while (enumerator1.MoveNext() && enumerator2.MoveNext()) { ArraySegment<byte> data1 = (ArraySegment<byte>)enumerator1.Current.Value; ArraySegment<byte> data2 = (ArraySegment<byte>)enumerator1.Current.Value; Assert.Equal(data1.Count, data2.Count); } } } catch (InvalidOperationException) { // some messages do not support DataBody property Stream bodyStream1 = original.BodyStream; Stream bodyStream2 = deserialized.BodyStream; Assert.Equal(bodyStream1.Length, bodyStream2.Length); } } if ((original.Sections & SectionFlag.AmqpValue) != 0) { Assert.Equal(original.ValueBody.Value, deserialized.ValueBody.Value); } if ((original.Sections & SectionFlag.AmqpSequence) != 0) { Assert.Equal(original.SequenceBody.Count(), deserialized.SequenceBody.Count()); using(IEnumerator<AmqpSequence> enumerator1 = original.SequenceBody.GetEnumerator()) using(IEnumerator<AmqpSequence> enumerator2 = deserialized.SequenceBody.GetEnumerator()) { while (enumerator1.MoveNext() && enumerator2.MoveNext()) { Assert.Equal(enumerator1.Current.List.Count, enumerator2.Current.List.Count); for(int i = 0; i < enumerator1.Current.List.Count; i++) { Assert.Equal(enumerator1.Current.List[i], enumerator2.Current.List[i]); } } } } }
static void RunSerializationTest(AmqpMessage message) { AmqpMessage deserialized = AmqpMessage.CreateAmqpStreamMessage(new BufferListStream(ReadMessagePayLoad(message, 89))); ValidateMessage(message, deserialized); }
AmqpMessage PopulateAmqpMessageForSend(AmqpMessage message) { MethodConverter.PopulateAmqpMessageFromMethodResponse(message, this); return(message); }
private void DisposeDelivery(AmqpMessage amqpMessage, bool settled, Accepted acceptedOutcome) { _receivingAmqpLink.DisposeDelivery(amqpMessage, settled, acceptedOutcome); }
public static ServiceBusReceivedMessage AmqpMessageToSBMessage(AmqpMessage amqpMessage, bool isPeeked = false) { Argument.AssertNotNull(amqpMessage, nameof(amqpMessage)); AmqpAnnotatedMessage annotatedMessage; // body if ((amqpMessage.BodyType & SectionFlag.Data) != 0 && amqpMessage.DataBody != null) { annotatedMessage = new AmqpAnnotatedMessage(AmqpMessageBody.FromData(MessageBody.FromDataSegments(amqpMessage.DataBody))); } else if ((amqpMessage.BodyType & SectionFlag.AmqpValue) != 0 && amqpMessage.ValueBody?.Value != null) { if (TryGetNetObjectFromAmqpObject(amqpMessage.ValueBody.Value, MappingType.MessageBody, out object netObject)) { annotatedMessage = new AmqpAnnotatedMessage(AmqpMessageBody.FromValue(netObject)); } else { throw new NotSupportedException(Resources.InvalidAmqpMessageValueBody.FormatForUser(amqpMessage.ValueBody.Value.GetType())); } } else if ((amqpMessage.BodyType & SectionFlag.AmqpSequence) != 0) { annotatedMessage = new AmqpAnnotatedMessage( AmqpMessageBody.FromSequence(amqpMessage.SequenceBody.Select(s => (IList <object>)s.List).ToList())); } // default to using an empty Data section if no data else { annotatedMessage = new AmqpAnnotatedMessage(new AmqpMessageBody(Enumerable.Empty <ReadOnlyMemory <byte> >())); } ServiceBusReceivedMessage sbMessage = new ServiceBusReceivedMessage(annotatedMessage); SectionFlag sections = amqpMessage.Sections; // properties if ((sections & SectionFlag.Properties) != 0) { if (amqpMessage.Properties.MessageId != null) { annotatedMessage.Properties.MessageId = new AmqpMessageId(amqpMessage.Properties.MessageId.ToString()); } if (amqpMessage.Properties.CorrelationId != null) { annotatedMessage.Properties.CorrelationId = new AmqpMessageId(amqpMessage.Properties.CorrelationId.ToString()); } if (amqpMessage.Properties.ContentType.Value != null) { annotatedMessage.Properties.ContentType = amqpMessage.Properties.ContentType.Value; } if (amqpMessage.Properties.ContentEncoding.Value != null) { annotatedMessage.Properties.ContentEncoding = amqpMessage.Properties.ContentEncoding.Value; } if (amqpMessage.Properties.Subject != null) { annotatedMessage.Properties.Subject = amqpMessage.Properties.Subject; } if (amqpMessage.Properties.To != null) { annotatedMessage.Properties.To = new AmqpAddress(amqpMessage.Properties.To.ToString()); } if (amqpMessage.Properties.ReplyTo != null) { annotatedMessage.Properties.ReplyTo = new AmqpAddress(amqpMessage.Properties.ReplyTo.ToString()); } if (amqpMessage.Properties.GroupId != null) { annotatedMessage.Properties.GroupId = amqpMessage.Properties.GroupId; } if (amqpMessage.Properties.ReplyToGroupId != null) { annotatedMessage.Properties.ReplyToGroupId = amqpMessage.Properties.ReplyToGroupId; } if (amqpMessage.Properties.GroupSequence != null) { annotatedMessage.Properties.GroupSequence = amqpMessage.Properties.GroupSequence; } if (amqpMessage.Properties.UserId != null) { annotatedMessage.Properties.UserId = amqpMessage.Properties.UserId; } if (amqpMessage.Properties.CreationTime != null) { annotatedMessage.Properties.CreationTime = amqpMessage.Properties.CreationTime; } if (amqpMessage.Properties.AbsoluteExpiryTime != null) { annotatedMessage.Properties.AbsoluteExpiryTime = amqpMessage.Properties.AbsoluteExpiryTime >= DateTimeOffset.MaxValue.UtcDateTime ? DateTimeOffset.MaxValue : amqpMessage.Properties.AbsoluteExpiryTime; } } // Do application properties before message annotations, because the application properties // can be updated by entries from message annotation. if ((sections & SectionFlag.ApplicationProperties) != 0) { foreach (var pair in amqpMessage.ApplicationProperties.Map) { if (TryGetNetObjectFromAmqpObject(pair.Value, MappingType.ApplicationProperty, out var netObject)) { annotatedMessage.ApplicationProperties[pair.Key.ToString()] = netObject; } } } // message annotations if ((sections & SectionFlag.MessageAnnotations) != 0) { foreach (var pair in amqpMessage.MessageAnnotations.Map) { var key = pair.Key.ToString(); switch (key) { case AmqpMessageConstants.EnqueuedTimeUtcName: annotatedMessage.MessageAnnotations[AmqpMessageConstants.EnqueuedTimeUtcName] = pair.Value; break; case AmqpMessageConstants.ScheduledEnqueueTimeUtcName: annotatedMessage.MessageAnnotations[AmqpMessageConstants.ScheduledEnqueueTimeUtcName] = pair.Value; break; case AmqpMessageConstants.SequenceNumberName: annotatedMessage.MessageAnnotations[AmqpMessageConstants.SequenceNumberName] = pair.Value; break; case AmqpMessageConstants.EnqueueSequenceNumberName: annotatedMessage.MessageAnnotations[AmqpMessageConstants.EnqueueSequenceNumberName] = pair.Value; break; case AmqpMessageConstants.LockedUntilName: DateTimeOffset lockedUntil = (DateTime)pair.Value >= DateTimeOffset.MaxValue.UtcDateTime ? DateTimeOffset.MaxValue : (DateTime)pair.Value; annotatedMessage.MessageAnnotations[AmqpMessageConstants.LockedUntilName] = lockedUntil.UtcDateTime; break; case AmqpMessageConstants.PartitionKeyName: annotatedMessage.MessageAnnotations[AmqpMessageConstants.PartitionKeyName] = pair.Value; break; case AmqpMessageConstants.PartitionIdName: annotatedMessage.MessageAnnotations[AmqpMessageConstants.PartitionIdName] = pair.Value; break; case AmqpMessageConstants.ViaPartitionKeyName: annotatedMessage.MessageAnnotations[AmqpMessageConstants.ViaPartitionKeyName] = pair.Value; break; case AmqpMessageConstants.DeadLetterSourceName: annotatedMessage.MessageAnnotations[AmqpMessageConstants.DeadLetterSourceName] = pair.Value; break; default: if (TryGetNetObjectFromAmqpObject(pair.Value, MappingType.ApplicationProperty, out var netObject)) { annotatedMessage.MessageAnnotations[key] = netObject; } break; } } } // delivery annotations if (amqpMessage.DeliveryAnnotations != null) { foreach (KeyValuePair <MapKey, object> kvp in amqpMessage.DeliveryAnnotations.Map) { if (TryGetNetObjectFromAmqpObject(kvp.Value, MappingType.ApplicationProperty, out var netObject)) { annotatedMessage.DeliveryAnnotations[kvp.Key.ToString()] = netObject; } } } // header if ((sections & SectionFlag.Header) != 0) { if (amqpMessage.Header.Ttl != null) { annotatedMessage.Header.TimeToLive = TimeSpan.FromMilliseconds(amqpMessage.Header.Ttl.Value); } if (amqpMessage.Header.DeliveryCount != null) { annotatedMessage.Header.DeliveryCount = isPeeked ? (amqpMessage.Header.DeliveryCount.Value) : (amqpMessage.Header.DeliveryCount.Value + 1); } annotatedMessage.Header.Durable = amqpMessage.Header.Durable; annotatedMessage.Header.FirstAcquirer = amqpMessage.Header.FirstAcquirer; annotatedMessage.Header.Priority = amqpMessage.Header.Priority; } // footer if (amqpMessage.DeliveryTag.Count == GuidSizeInBytes) { Span <byte> guidBytes = stackalloc byte[GuidSizeInBytes]; amqpMessage.DeliveryTag.AsSpan().CopyTo(guidBytes); if (!MemoryMarshal.TryRead <Guid>(guidBytes, out var lockTokenGuid)) { lockTokenGuid = new Guid(guidBytes.ToArray()); } sbMessage.LockTokenGuid = lockTokenGuid; } amqpMessage.Dispose(); return(sbMessage); }
void OnMessage(AmqpMessage message) { this.messages.EnqueueAndDispatch(message, null, false); this.Link.DisposeDelivery(message, true, message.State); }
public void CreateBatchFromMessagesAllowNoPartitionKey(string partitionKey) { var converter = new AmqpMessageConverter(); Assert.That(() => converter.CreateBatchFromMessages(new[] { AmqpMessage.Create() }, partitionKey), Throws.Nothing); }
public void AcceptMessage(AmqpMessage message, bool batchable) { bool settled = this.Settings.SettleType != SettleMode.SettleOnDispose; this.AcceptMessage(message, settled, batchable); }
public void FromMessageTest_AllProperties() { // Arrange byte[] bytes = { 1, 2, 3, 4 }; string messageId = Guid.NewGuid().ToString(); string correlationId = Guid.NewGuid().ToString(); string contentType = "UTF-8"; string contentEncoding = "application/json"; string to = "d1"; string userId = "userId1"; var expiryTime = new DateTime(2018, 2, 3, 02, 03, 04, DateTimeKind.Utc); string creationTime = new DateTime(2018, 1, 1, 02, 03, 04, DateTimeKind.Utc).ToString("o"); var enqueuedTime = new DateTime(2018, 4, 5, 04, 05, 06, DateTimeKind.Utc); byte deliveryCount = 10; string lockToken = Guid.NewGuid().ToString(); ulong sequenceNumber = 100; string messageSchema = "testSchema"; string operation = "foo"; string inputName = "inputName"; string outputName = "outputName"; string connectionDeviceId = "edgeDevice1"; string connectionModuleId = "module1"; var systemProperties = new Dictionary <string, string> { [SystemProperties.MessageId] = messageId, [SystemProperties.MsgCorrelationId] = correlationId, [SystemProperties.ContentType] = contentType, [SystemProperties.ContentEncoding] = contentEncoding, [SystemProperties.To] = to, [SystemProperties.UserId] = userId, [SystemProperties.ExpiryTimeUtc] = expiryTime.ToString("o"), [SystemProperties.EnqueuedTime] = enqueuedTime.ToString("o"), [SystemProperties.DeliveryCount] = deliveryCount.ToString(), [SystemProperties.LockToken] = lockToken, [SystemProperties.SequenceNumber] = sequenceNumber.ToString(), [SystemProperties.MessageSchema] = messageSchema, [SystemProperties.CreationTime] = creationTime, [SystemProperties.Operation] = operation, [SystemProperties.InputName] = inputName, [SystemProperties.OutputName] = outputName, [SystemProperties.ConnectionDeviceId] = connectionDeviceId, [SystemProperties.ConnectionModuleId] = connectionModuleId }; var properties = new Dictionary <string, string> { ["Prop1"] = "Value1", ["Prop2"] = "Value2" }; byte[] GetMessageBody(AmqpMessage sourceMessage) { using (var ms = new MemoryStream()) { sourceMessage.BodyStream.CopyTo(ms); return(ms.ToArray()); } } var message = new EdgeMessage(bytes, properties, systemProperties); var messageConverter = new AmqpMessageConverter(); // Act using (AmqpMessage amqpMessage = messageConverter.FromMessage(message)) { // Assert Assert.NotNull(amqpMessage); Assert.Equal(bytes, GetMessageBody(amqpMessage)); Assert.Equal(messageId, amqpMessage.Properties.MessageId.ToString()); Assert.Equal(correlationId, amqpMessage.Properties.CorrelationId.ToString()); Assert.Equal(contentEncoding, amqpMessage.Properties.ContentEncoding.ToString()); Assert.Equal(contentType, amqpMessage.Properties.ContentType.ToString()); Assert.Equal(to, amqpMessage.Properties.To.ToString()); Assert.Equal(userId, Encoding.UTF8.GetString(amqpMessage.Properties.UserId.Array)); Assert.Equal(expiryTime, amqpMessage.Properties.AbsoluteExpiryTime.HasValue ? amqpMessage.Properties.AbsoluteExpiryTime.Value : DateTime.MinValue); Assert.Equal(enqueuedTime, amqpMessage.MessageAnnotations.Map[Constants.MessageAnnotationsEnqueuedTimeKey]); Assert.Equal(deliveryCount, amqpMessage.MessageAnnotations.Map[Constants.MessageAnnotationsDeliveryCountKey]); Assert.Equal(lockToken, amqpMessage.MessageAnnotations.Map[Constants.MessageAnnotationsLockTokenName]); Assert.Equal(sequenceNumber, amqpMessage.MessageAnnotations.Map[Constants.MessageAnnotationsSequenceNumberName]); Assert.Equal(inputName, amqpMessage.MessageAnnotations.Map[Constants.MessageAnnotationsInputNameKey]); Assert.Equal(connectionDeviceId, amqpMessage.MessageAnnotations.Map[Constants.MessageAnnotationsConnectionDeviceId]); Assert.Equal(connectionModuleId, amqpMessage.MessageAnnotations.Map[Constants.MessageAnnotationsConnectionModuleId]); Assert.Equal(messageSchema, amqpMessage.ApplicationProperties.Map[Constants.MessagePropertiesMessageSchemaKey]); Assert.Equal(creationTime, amqpMessage.ApplicationProperties.Map[Constants.MessagePropertiesCreationTimeKey]); Assert.Equal(operation, amqpMessage.ApplicationProperties.Map[Constants.MessagePropertiesOperationKey]); Assert.False(amqpMessage.ApplicationProperties.Map.TryGetValue(Constants.MessagePropertiesOutputNameKey, out string _)); Assert.Equal("Value1", amqpMessage.ApplicationProperties.Map["Prop1"].ToString()); Assert.Equal("Value2", amqpMessage.ApplicationProperties.Map["Prop2"].ToString()); } }
public void ModifyMessage(AmqpMessage message, bool deliveryFailed, bool deliverElseWhere, Fields messageAttributes) { Modified modified = new Modified(); modified.DeliveryFailed = deliveryFailed; modified.UndeliverableHere = deliverElseWhere; modified.MessageAnnotations = messageAttributes; this.DisposeMessage(message, modified, true, false); }
public void ToMessageTest_AllProperties() { // Arrange IMessage receivedMessage; byte[] bytes = { 1, 2, 3, 4 }; string messageId = Guid.NewGuid().ToString(); string correlationId = Guid.NewGuid().ToString(); string contentType = "application/json"; string contentEncoding = "UTF-8"; string to = "d1"; string userId = "userId1"; var expiryTime = new DateTime(2018, 2, 3, 02, 03, 04, DateTimeKind.Utc); string creationTime = new DateTime(2018, 1, 1, 02, 03, 04, DateTimeKind.Utc).ToString("o"); var enqueuedTime = new DateTime(2018, 4, 5, 04, 05, 06, DateTimeKind.Utc); byte deliveryCount = 10; string lockToken = Guid.NewGuid().ToString(); ulong sequenceNumber = 100; string messageSchema = "testSchema"; string operation = "foo"; string outputName = "output1"; using (AmqpMessage amqpMessage = AmqpMessage.Create(new Data { Value = new ArraySegment <byte>(bytes) })) { amqpMessage.Properties.MessageId = messageId; amqpMessage.Properties.CorrelationId = correlationId; amqpMessage.Properties.ContentType = contentType; amqpMessage.Properties.ContentEncoding = contentEncoding; amqpMessage.Properties.To = to; amqpMessage.Properties.UserId = new ArraySegment <byte>(Encoding.UTF8.GetBytes(userId)); amqpMessage.Properties.AbsoluteExpiryTime = expiryTime; amqpMessage.MessageAnnotations.Map[Constants.MessageAnnotationsEnqueuedTimeKey] = enqueuedTime; amqpMessage.MessageAnnotations.Map[Constants.MessageAnnotationsDeliveryCountKey] = deliveryCount; amqpMessage.MessageAnnotations.Map[Constants.MessageAnnotationsLockTokenName] = lockToken; amqpMessage.MessageAnnotations.Map[Constants.MessageAnnotationsSequenceNumberName] = sequenceNumber; amqpMessage.ApplicationProperties.Map[Constants.MessagePropertiesMessageSchemaKey] = messageSchema; amqpMessage.ApplicationProperties.Map[Constants.MessagePropertiesCreationTimeKey] = creationTime; amqpMessage.ApplicationProperties.Map[Constants.MessagePropertiesOperationKey] = operation; amqpMessage.ApplicationProperties.Map[Constants.MessagePropertiesOutputNameKey] = outputName; amqpMessage.ApplicationProperties.Map["Prop1"] = "Value1"; amqpMessage.ApplicationProperties.Map["Prop2"] = "Value2"; var messageConverter = new AmqpMessageConverter(); // Act receivedMessage = messageConverter.ToMessage(amqpMessage); } // Assert Assert.NotNull(receivedMessage); Assert.Equal(receivedMessage.Body, bytes); Assert.Equal(15, receivedMessage.SystemProperties.Count); Assert.Equal(2, receivedMessage.Properties.Count); Assert.Equal(receivedMessage.SystemProperties[SystemProperties.MessageId], messageId); Assert.Equal(receivedMessage.SystemProperties[SystemProperties.MsgCorrelationId], correlationId); Assert.Equal(receivedMessage.SystemProperties[SystemProperties.ContentType], contentType); Assert.Equal(receivedMessage.SystemProperties[SystemProperties.ContentEncoding], contentEncoding); Assert.Equal(receivedMessage.SystemProperties[SystemProperties.To], to); Assert.Equal(receivedMessage.SystemProperties[SystemProperties.UserId], userId); Assert.Equal(receivedMessage.SystemProperties[SystemProperties.ExpiryTimeUtc], expiryTime.ToString("o")); Assert.Equal(receivedMessage.SystemProperties[SystemProperties.EnqueuedTime], enqueuedTime.ToString("o")); Assert.Equal(receivedMessage.SystemProperties[SystemProperties.DeliveryCount], deliveryCount.ToString()); Assert.Equal(receivedMessage.SystemProperties[SystemProperties.LockToken], lockToken); Assert.Equal(receivedMessage.SystemProperties[SystemProperties.SequenceNumber], sequenceNumber.ToString()); Assert.Equal(receivedMessage.SystemProperties[SystemProperties.MessageSchema], messageSchema); Assert.Equal(receivedMessage.SystemProperties[SystemProperties.CreationTime], creationTime); Assert.Equal(receivedMessage.SystemProperties[SystemProperties.Operation], operation); Assert.Equal(receivedMessage.SystemProperties[SystemProperties.OutputName], outputName); Assert.Equal("Value1", receivedMessage.Properties["Prop1"]); Assert.Equal("Value2", receivedMessage.Properties["Prop2"]); }
void CompleteInternal(AmqpMessage message, bool syncComplete) { if (Interlocked.Exchange(ref this.completed, 1) == 0) { this.message = message; this.Complete(syncComplete); } }
/// <summary> /// Converts a given <see cref="AmqpMessage" /> source into its corresponding /// <see cref="EventData" /> representation. /// </summary> /// /// <param name="source">The source message to convert.</param> /// /// <returns>The event that represents the converted AMQP message.</returns> /// /// <remarks> /// The caller is assumed to hold ownership over the specified message, including /// ensuring proper disposal. /// </remarks> /// public virtual EventData CreateEventFromMessage(AmqpMessage source) { Argument.AssertNotNull(source, nameof(source)); return(BuildEventFromAmqpMessage(source)); }
/// <summary> /// Copies the Message instance's properties to the AmqpMessage instance. /// </summary> public static void UpdateAmqpMessageHeadersAndProperties(AmqpMessage amqpMessage, Message data, bool copyUserProperties = true) { amqpMessage.Properties.MessageId = data.MessageId; if (data.To != null) { amqpMessage.Properties.To = data.To; } if (!data.ExpiryTimeUtc.Equals(default(DateTime))) { amqpMessage.Properties.AbsoluteExpiryTime = data.ExpiryTimeUtc; } if (data.CorrelationId != null) { amqpMessage.Properties.CorrelationId = data.CorrelationId; } if (data.UserId != null) { amqpMessage.Properties.UserId = new ArraySegment<byte>(Encoding.UTF8.GetBytes(data.UserId)); } if (amqpMessage.ApplicationProperties == null) { amqpMessage.ApplicationProperties = new ApplicationProperties(); } object deliveryAckSetting; if (data.SystemProperties.TryGetValue(MessageSystemPropertyNames.Ack, out deliveryAckSetting)) { amqpMessage.ApplicationProperties.Map["iothub-ack"] = (string)deliveryAckSetting; } if (copyUserProperties && data.Properties.Count > 0) { foreach (var pair in data.Properties) { object amqpObject; if (TryGetAmqpObjectFromNetObject(pair.Value, MappingType.ApplicationProperty, out amqpObject)) { amqpMessage.ApplicationProperties.Map[pair.Key] = amqpObject; } } } }
/// <summary> /// Parses the annotations set by the Event Hubs service on the <see cref="AmqpMessage"/> /// associated with an event, extracting them into a consumable form. /// </summary> /// /// <param name="source">The message to use as the source of the event.</param> /// /// <returns>The <see cref="ParsedAnnotations" /> parsed from the source message.</returns> /// private static ParsedAnnotations ParseSystemAnnotations(AmqpMessage source) { var systemProperties = new ParsedAnnotations { ServiceAnnotations = new Dictionary <string, object>() }; object amqpValue; object propertyValue; // Process the message annotations. if (source.Sections.HasFlag(SectionFlag.MessageAnnotations)) { Annotations annotations = source.MessageAnnotations.Map; var processed = new HashSet <string>(); if ((annotations.TryGetValue(AmqpProperty.EnqueuedTime, out amqpValue)) && (TryCreateEventPropertyForAmqpProperty(amqpValue, out propertyValue))) { systemProperties.EnqueuedTime = propertyValue switch { DateTime dateValue => new DateTimeOffset(dateValue, TimeSpan.Zero), long longValue => new DateTimeOffset(longValue, TimeSpan.Zero), _ => (DateTimeOffset)propertyValue }; processed.Add(AmqpProperty.EnqueuedTime.ToString()); } if ((annotations.TryGetValue(AmqpProperty.SequenceNumber, out amqpValue)) && (TryCreateEventPropertyForAmqpProperty(amqpValue, out propertyValue))) { systemProperties.SequenceNumber = (long)propertyValue; processed.Add(AmqpProperty.SequenceNumber.ToString()); } if ((annotations.TryGetValue(AmqpProperty.Offset, out amqpValue)) && (TryCreateEventPropertyForAmqpProperty(amqpValue, out propertyValue)) && (long.TryParse((string)propertyValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out var offset))) { systemProperties.Offset = offset; processed.Add(AmqpProperty.Offset.ToString()); } if ((annotations.TryGetValue(AmqpProperty.PartitionKey, out amqpValue)) && (TryCreateEventPropertyForAmqpProperty(amqpValue, out propertyValue))) { systemProperties.PartitionKey = (string)propertyValue; processed.Add(AmqpProperty.PartitionKey.ToString()); } string key; foreach (KeyValuePair <MapKey, object> pair in annotations) { key = pair.Key.ToString(); if ((!processed.Contains(key)) && (TryCreateEventPropertyForAmqpProperty(pair.Value, out propertyValue))) { systemProperties.ServiceAnnotations.Add(key, propertyValue); processed.Add(key); } } } // Process the delivery annotations. if (source.Sections.HasFlag(SectionFlag.DeliveryAnnotations)) { if ((source.DeliveryAnnotations.Map.TryGetValue(AmqpProperty.PartitionLastEnqueuedTimeUtc, out amqpValue)) && (TryCreateEventPropertyForAmqpProperty(amqpValue, out propertyValue))) { systemProperties.LastEnqueuedTime = propertyValue switch { DateTime dateValue => new DateTimeOffset(dateValue, TimeSpan.Zero), long longValue => new DateTimeOffset(longValue, TimeSpan.Zero), _ => (DateTimeOffset)propertyValue }; } if ((source.DeliveryAnnotations.Map.TryGetValue(AmqpProperty.PartitionLastEnqueuedSequenceNumber, out amqpValue)) && (TryCreateEventPropertyForAmqpProperty(amqpValue, out propertyValue))) { systemProperties.LastSequenceNumber = (long)propertyValue; } if ((source.DeliveryAnnotations.Map.TryGetValue(AmqpProperty.PartitionLastEnqueuedOffset, out amqpValue)) && (TryCreateEventPropertyForAmqpProperty(amqpValue, out propertyValue)) && (long.TryParse((string)propertyValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out var offset))) { systemProperties.LastOffset = offset; } if ((source.DeliveryAnnotations.Map.TryGetValue(AmqpProperty.LastPartitionPropertiesRetrievalTimeUtc, out amqpValue)) && (TryCreateEventPropertyForAmqpProperty(amqpValue, out propertyValue))) { systemProperties.LastReceivedTime = propertyValue switch { DateTime dateValue => new DateTimeOffset(dateValue, TimeSpan.Zero), long longValue => new DateTimeOffset(longValue, TimeSpan.Zero), _ => (DateTimeOffset)propertyValue }; } } // Process the properties annotations if (source.Sections.HasFlag(SectionFlag.Properties)) { Properties properties = source.Properties; void conditionalAdd(string name, object value, bool condition) { if (condition) { systemProperties.ServiceAnnotations.Add(name, value); } } conditionalAdd(Properties.MessageIdName, properties.MessageId, properties.MessageId != null); conditionalAdd(Properties.UserIdName, properties.UserId, properties.UserId.Array != null); conditionalAdd(Properties.ToName, properties.To, properties.To != null); conditionalAdd(Properties.SubjectName, properties.Subject, properties.Subject != null); conditionalAdd(Properties.ReplyToName, properties.ReplyTo, properties.ReplyTo != null); conditionalAdd(Properties.CorrelationIdName, properties.CorrelationId, properties.CorrelationId != null); conditionalAdd(Properties.ContentTypeName, properties.ContentType, properties.ContentType.Value != null); conditionalAdd(Properties.ContentEncodingName, properties.ContentEncoding, properties.ContentEncoding.Value != null); conditionalAdd(Properties.AbsoluteExpiryTimeName, properties.AbsoluteExpiryTime, properties.AbsoluteExpiryTime != null); conditionalAdd(Properties.CreationTimeName, properties.CreationTime, properties.CreationTime != null); conditionalAdd(Properties.GroupIdName, properties.GroupId, properties.GroupId != null); conditionalAdd(Properties.GroupSequenceName, properties.GroupSequence, properties.GroupSequence != null); conditionalAdd(Properties.ReplyToGroupIdName, properties.ReplyToGroupId, properties.ReplyToGroupId != null); } return(systemProperties); }
/// <summary> /// /// </summary> /// <param name="retryPolicy"></param> /// <param name="fromSequenceNumber"></param> /// <param name="messageCount"></param> /// <param name="sessionId"></param> /// <param name="receiveLinkName"></param> /// <param name="timeout"></param> /// <param name="cancellationToken"></param> /// <returns></returns> internal async Task <IEnumerable <ServiceBusMessage> > PeekInternal( ServiceBusRetryPolicy retryPolicy, long?fromSequenceNumber, int messageCount, string sessionId, string receiveLinkName, TimeSpan timeout, CancellationToken cancellationToken = default) { var stopWatch = new Stopwatch(); stopWatch.Start(); AmqpRequestMessage amqpRequestMessage = AmqpRequestMessage.CreateRequest( ManagementConstants.Operations.PeekMessageOperation, timeout, null); await AquireAccessTokenAsync(cancellationToken).ConfigureAwait(false); if (receiveLinkName != null) { // include associated link for service optimization amqpRequestMessage.AmqpMessage.ApplicationProperties.Map[ManagementConstants.Request.AssociatedLinkName] = receiveLinkName; } amqpRequestMessage.Map[ManagementConstants.Properties.FromSequenceNumber] = fromSequenceNumber ?? LastPeekedSequenceNumber + 1; amqpRequestMessage.Map[ManagementConstants.Properties.MessageCount] = messageCount; if (!string.IsNullOrWhiteSpace(sessionId)) { amqpRequestMessage.Map[ManagementConstants.Properties.SessionId] = sessionId; } RequestResponseAmqpLink link = await ManagementLink.GetOrCreateAsync( UseMinimum(ConnectionScope.SessionTimeout, timeout.CalculateRemaining(stopWatch.Elapsed))) .ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); using AmqpMessage responseAmqpMessage = await link.RequestAsync( amqpRequestMessage.AmqpMessage, timeout.CalculateRemaining(stopWatch.Elapsed)) .ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); AmqpResponseMessage amqpResponseMessage = AmqpResponseMessage.CreateResponse(responseAmqpMessage); var messages = new List <ServiceBusMessage>(); //AmqpError.ThrowIfErrorResponse(responseAmqpMessage, EntityName); if (amqpResponseMessage.StatusCode == AmqpResponseStatusCode.OK) { ServiceBusMessage message = null; IEnumerable <AmqpMap> messageList = amqpResponseMessage.GetListValue <AmqpMap>(ManagementConstants.Properties.Messages); foreach (AmqpMap entry in messageList) { var payload = (ArraySegment <byte>)entry[ManagementConstants.Properties.Message]; var amqpMessage = AmqpMessage.CreateAmqpStreamMessage(new BufferListStream(new[] { payload }), true); message = AmqpMessageConverter.AmqpMessageToSBMessage(amqpMessage, true); messages.Add(message); } if (message != null) { LastPeekedSequenceNumber = message.SystemProperties.SequenceNumber; } return(messages); } if (amqpResponseMessage.StatusCode == AmqpResponseStatusCode.NoContent || (amqpResponseMessage.StatusCode == AmqpResponseStatusCode.NotFound && Equals(AmqpClientConstants.MessageNotFoundError, amqpResponseMessage.GetResponseErrorCondition()))) { return(messages); } // TODO throw correct exception throw new Exception(); }
/// <summary> /// Copies the Message instance's properties to the AmqpMessage instance. /// </summary> public static void UpdateAmqpMessageHeadersAndProperties(AmqpMessage amqpMessage, Message data, bool copyUserProperties = true) { amqpMessage.Properties.MessageId = data.MessageId; if (data.To != null) { amqpMessage.Properties.To = data.To; } if (!data.ExpiryTimeUtc.Equals(default(DateTime))) { amqpMessage.Properties.AbsoluteExpiryTime = data.ExpiryTimeUtc; } if (data.CorrelationId != null) { amqpMessage.Properties.CorrelationId = data.CorrelationId; } if (data.UserId != null) { amqpMessage.Properties.UserId = new ArraySegment <byte>(Encoding.UTF8.GetBytes(data.UserId)); } if (amqpMessage.ApplicationProperties == null) { amqpMessage.ApplicationProperties = new ApplicationProperties(); } object propertyValue; if (data.SystemProperties.TryGetValue(MessageSystemPropertyNames.Ack, out propertyValue)) { amqpMessage.ApplicationProperties.Map["iothub-ack"] = (string)propertyValue; } if (data.SystemProperties.TryGetValue(MessageSystemPropertyNames.MessageSchema, out propertyValue)) { amqpMessage.ApplicationProperties.Map[MessageSystemPropertyNames.MessageSchema] = (string)propertyValue; } if (data.SystemProperties.TryGetValue(MessageSystemPropertyNames.CreationTimeUtc, out propertyValue)) { amqpMessage.ApplicationProperties.Map[MessageSystemPropertyNames.CreationTimeUtc] = ((DateTime)propertyValue).ToString("o"); // Convert to string that complies with ISO 8601 } if (data.SystemProperties.TryGetValue(MessageSystemPropertyNames.ContentType, out propertyValue)) { amqpMessage.Properties.ContentType = (string)propertyValue; } if (data.SystemProperties.TryGetValue(MessageSystemPropertyNames.ContentEncoding, out propertyValue)) { amqpMessage.Properties.ContentEncoding = (string)propertyValue; } if (data.SystemProperties.TryGetValue(MessageSystemPropertyNames.OutputName, out propertyValue)) { amqpMessage.ApplicationProperties.Map[MessageSystemPropertyNames.OutputName] = (string)propertyValue; } if (data.SystemProperties.TryGetValue(MessageSystemPropertyNames.InterfaceId, out propertyValue)) { amqpMessage.MessageAnnotations.Map[MessageSystemPropertyNames.InterfaceId] = (string)propertyValue; } if (copyUserProperties && data.Properties.Count > 0) { foreach (var pair in data.Properties) { object amqpObject; if (TryGetAmqpObjectFromNetObject(pair.Value, MappingType.ApplicationProperty, out amqpObject)) { amqpMessage.ApplicationProperties.Map[pair.Key] = amqpObject; } } } if (IoTHubClientDiagnostic.HasDiagnosticProperties(data)) { amqpMessage.MessageAnnotations.Map[AmqpDiagIdKey] = data.SystemProperties[MessageSystemPropertyNames.DiagId]; amqpMessage.MessageAnnotations.Map[AmqpDiagCorrelationContextKey] = data.SystemProperties[MessageSystemPropertyNames.DiagCorrelationContext]; } }
public async Task SendMessageWithFeedbackExactlyOnceModeTest() { // Arrange var metadataStore = Mock.Of <IMetadataStore>(); var feedbackStatus = FeedbackStatus.Abandon; var deviceListener = new Mock <IDeviceListener>(); deviceListener.Setup(d => d.ProcessMessageFeedbackAsync(It.IsAny <string>(), It.IsAny <FeedbackStatus>())) .Callback <string, FeedbackStatus>((m, s) => feedbackStatus = s) .Returns(Task.CompletedTask); AmqpMessage receivedAmqpMessage = null; var identity = Mock.Of <IIdentity>(i => i.Id == "d1"); var connectionHandler = Mock.Of <IConnectionHandler>(c => c.GetDeviceListener() == Task.FromResult(deviceListener.Object)); var amqpAuthenticator = new Mock <IAmqpAuthenticator>(); amqpAuthenticator.Setup(c => c.AuthenticateAsync("d1", Option.None <string>())).ReturnsAsync(true); Mock <ICbsNode> cbsNodeMock = amqpAuthenticator.As <ICbsNode>(); ICbsNode cbsNode = cbsNodeMock.Object; var amqpConnection = Mock.Of <IAmqpConnection>( c => c.FindExtension <IConnectionHandler>() == connectionHandler && c.FindExtension <ICbsNode>() == cbsNode); var amqpSession = Mock.Of <IAmqpSession>(s => s.Connection == amqpConnection); var amqpLinkSettings = new AmqpLinkSettings(); var sendingLink = Mock.Of <ISendingAmqpLink>(l => l.Session == amqpSession && !l.IsReceiver && l.Settings == amqpLinkSettings && l.State == AmqpObjectState.Opened); Mock.Get(sendingLink).Setup(s => s.SendMessageNoWait(It.IsAny <AmqpMessage>(), It.IsAny <ArraySegment <byte> >(), It.IsAny <ArraySegment <byte> >())) .Callback <AmqpMessage, ArraySegment <byte>, ArraySegment <byte> >((m, d, t) => { receivedAmqpMessage = m; }); var requestUri = new Uri("amqps://foo.bar/devices/d1"); var boundVariables = new Dictionary <string, string> { { "deviceid", "d1" } }; var messageConverter = new AmqpMessageConverter(); var sendingLinkHandler = new TestSendingLinkHandler(identity, sendingLink, requestUri, boundVariables, connectionHandler, messageConverter, QualityOfService.ExactlyOnce, metadataStore); var body = new byte[] { 0, 1, 2, 3 }; IMessage message = new EdgeMessage.Builder(body).Build(); var deliveryState = new Mock <DeliveryState>(new AmqpSymbol(string.Empty), AmqpConstants.AcceptedOutcome.DescriptorCode); var delivery = Mock.Of <Delivery>( d => d.State == deliveryState.Object && d.DeliveryTag == new ArraySegment <byte>(Guid.NewGuid().ToByteArray())); // Act await sendingLinkHandler.OpenAsync(TimeSpan.FromSeconds(5)); await sendingLinkHandler.SendMessage(message); // Assert Assert.NotNull(receivedAmqpMessage); Assert.Equal(body, receivedAmqpMessage.GetPayloadBytes()); // Act sendingLinkHandler.DispositionListener(delivery); await Task.Delay(TimeSpan.FromSeconds(5)); // Assert Assert.Equal(FeedbackStatus.Complete, feedbackStatus); Assert.Null(amqpLinkSettings.SndSettleMode); Assert.Equal((byte)ReceiverSettleMode.Second, amqpLinkSettings.RcvSettleMode); }
/// <summary> /// Copies the properties from the amqp message to the Message instance. /// </summary> public static void UpdateMessageHeaderAndProperties(AmqpMessage amqpMessage, Message message) { Fx.AssertAndThrow(amqpMessage.DeliveryTag != null, "AmqpMessage should always contain delivery tag."); message.DeliveryTag = amqpMessage.DeliveryTag; SectionFlag sections = amqpMessage.Sections; if ((sections & SectionFlag.Properties) != 0) { // Extract only the Properties that we support message.MessageId = amqpMessage.Properties.MessageId != null?amqpMessage.Properties.MessageId.ToString() : null; message.To = amqpMessage.Properties.To != null?amqpMessage.Properties.To.ToString() : null; if (amqpMessage.Properties.AbsoluteExpiryTime.HasValue) { message.ExpiryTimeUtc = amqpMessage.Properties.AbsoluteExpiryTime.Value; } message.CorrelationId = amqpMessage.Properties.CorrelationId != null?amqpMessage.Properties.CorrelationId.ToString() : null; if (!string.IsNullOrWhiteSpace(amqpMessage.Properties.ContentType.Value)) { message.ContentType = amqpMessage.Properties.ContentType.Value; } if (!string.IsNullOrWhiteSpace(amqpMessage.Properties.ContentEncoding.Value)) { message.ContentEncoding = amqpMessage.Properties.ContentEncoding.Value; } message.UserId = amqpMessage.Properties.UserId.Array != null?Encoding.UTF8.GetString(amqpMessage.Properties.UserId.Array, 0 /*index*/, amqpMessage.Properties.UserId.Array.Length) : null; } if ((sections & SectionFlag.MessageAnnotations) != 0) { if (amqpMessage.MessageAnnotations.Map.TryGetValue(LockTokenName, out string lockToken)) { message.LockToken = lockToken; } if (amqpMessage.MessageAnnotations.Map.TryGetValue(SequenceNumberName, out ulong sequenceNumber)) { message.SequenceNumber = sequenceNumber; } if (amqpMessage.MessageAnnotations.Map.TryGetValue(MessageSystemPropertyNames.EnqueuedTime, out DateTime enqueuedTime)) { message.EnqueuedTimeUtc = enqueuedTime; } if (amqpMessage.MessageAnnotations.Map.TryGetValue(MessageSystemPropertyNames.DeliveryCount, out byte deliveryCount)) { message.DeliveryCount = deliveryCount; } if (amqpMessage.MessageAnnotations.Map.TryGetValue(InputName, out string inputName)) { message.InputName = inputName; } if (amqpMessage.MessageAnnotations.Map.TryGetValue(MessageSystemPropertyNames.ConnectionDeviceId, out string connectionDeviceId)) { message.ConnectionDeviceId = connectionDeviceId; } if (amqpMessage.MessageAnnotations.Map.TryGetValue(MessageSystemPropertyNames.ConnectionModuleId, out string connectionModuleId)) { message.ConnectionModuleId = connectionModuleId; } } if ((sections & SectionFlag.ApplicationProperties) != 0) { foreach (KeyValuePair <MapKey, object> pair in amqpMessage.ApplicationProperties.Map) { object netObject = null; if (TryGetNetObjectFromAmqpObject(pair.Value, MappingType.ApplicationProperty, out netObject)) { var stringObject = netObject as string; if (stringObject != null) { switch (pair.Key.ToString()) { case MessageSystemPropertyNames.Operation: message.SystemProperties[pair.Key.ToString()] = stringObject; break; case MessageSystemPropertyNames.MessageSchema: message.MessageSchema = stringObject; break; case MessageSystemPropertyNames.CreationTimeUtc: message.CreationTimeUtc = DateTime.Parse(stringObject); break; default: message.Properties[pair.Key.ToString()] = stringObject; break; } } else { // TODO: RDBug 4093369 Handling of non-string property values in Amqp messages // Drop non-string properties and log an error Fx.Exception.TraceHandled(new InvalidDataException("IotHub does not accept non-string Amqp properties"), "MessageConverter.UpdateMessageHeaderAndProperties"); } } } } }
private static void UpdateEventDataHeaderAndProperties(AmqpMessage amqpMessage, EventData data) { //Fx.AssertAndThrow(amqpMessage.DeliveryTag != null, "AmqpMessage should always contain delivery tag."); //data.DeliveryTag = amqpMessage.DeliveryTag; SectionFlag sections = amqpMessage.Sections; if ((sections & SectionFlag.MessageAnnotations) != 0) { // services (e.g. IoTHub) assumes that all Amqp message annotation will get bubbled up so we will cycle // through the list and add them to system properties as well. foreach (var keyValuePair in amqpMessage.MessageAnnotations.Map) { if (data.Properties == null) { data.Properties = new Dictionary <string, object>(); } object netObject; if (TryGetNetObjectFromAmqpObject(keyValuePair.Value, MappingType.ApplicationProperty, out netObject)) { data.Properties[keyValuePair.Key.ToString()] = netObject; } } // Custom override for EventHub scenario. Note that these // "can" override existing properties, which is intentional as // in the EH these system properties take precedence over Amqp data. //string publisher; //if (amqpMessage.MessageAnnotations.Map.TryGetValue<string>(PublisherName, out publisher)) //{ // data.Publisher = publisher; //} //#if DEBUG // short partitionId; // if (amqpMessage.MessageAnnotations.Map.TryGetValue<short>(PartitionIdName, out partitionId)) // { // data.PartitionId = partitionId; // } //#endif if (data.SystemProperties == null) { data.SystemProperties = new EventData.SystemPropertiesCollection(); } string partitionKey; if (amqpMessage.MessageAnnotations.Map.TryGetValue(AmqpMessageConverter.PartitionKeyName, out partitionKey)) { data.SystemProperties.PartitionKey = partitionKey; } DateTime enqueuedTimeUtc; if (amqpMessage.MessageAnnotations.Map.TryGetValue(AmqpMessageConverter.EnqueuedTimeUtcName, out enqueuedTimeUtc)) { data.SystemProperties.EnqueuedTimeUtc = enqueuedTimeUtc; } long sequenceNumber; if (amqpMessage.MessageAnnotations.Map.TryGetValue(AmqpMessageConverter.SequenceNumberName, out sequenceNumber)) { data.SystemProperties.SequenceNumber = sequenceNumber; } string offset; if (amqpMessage.MessageAnnotations.Map.TryGetValue(AmqpMessageConverter.OffsetName, out offset)) { data.SystemProperties.Offset = offset; } } if ((sections & SectionFlag.ApplicationProperties) != 0) { foreach (KeyValuePair <MapKey, object> pair in amqpMessage.ApplicationProperties.Map) { if (data.Properties == null) { data.Properties = new Dictionary <string, object>(); } object netObject; if (TryGetNetObjectFromAmqpObject(pair.Value, MappingType.ApplicationProperty, out netObject)) { data.Properties[pair.Key.ToString()] = netObject; } } } //if ((sections & SectionFlag.Properties) != 0) //{ // var properties = amqpMessage.Properties; // AddIfTrue(data.SystemProperties, properties, p => p.MessageId != null, Properties.MessageIdName, p => p.MessageId.ToString()); // AddIfTrue(data.SystemProperties, properties, p => p.UserId.Array != null, Properties.UserIdName, p => p.UserId); // AddIfTrue(data.SystemProperties, properties, p => p.To != null, Properties.ToName, p => p.To.ToString()); // AddIfTrue(data.SystemProperties, properties, p => p.Subject != null, Properties.SubjectName, p => p.Subject); // AddIfTrue(data.SystemProperties, properties, p => p.ReplyTo != null, Properties.ReplyToName, p => p.ReplyTo.ToString()); // AddIfTrue(data.SystemProperties, properties, p => p.CorrelationId != null, Properties.CorrelationIdName, p => p.CorrelationId.ToString()); // AddIfTrue(data.SystemProperties, properties, p => p.ContentType.Value != null, Properties.ContentTypeName, p => p.ContentType.ToString()); // AddIfTrue(data.SystemProperties, properties, p => p.ContentEncoding.Value != null, Properties.ContentEncodingName, p => p.ContentEncoding.ToString()); // AddIfTrue(data.SystemProperties, properties, p => p.AbsoluteExpiryTime != null, Properties.AbsoluteExpiryTimeName, p => p.AbsoluteExpiryTime); // AddIfTrue(data.SystemProperties, properties, p => p.CreationTime != null, Properties.CreationTimeName, p => p.CreationTime); // AddIfTrue(data.SystemProperties, properties, p => p.GroupId != null, Properties.GroupIdName, p => p.GroupId); // AddIfTrue(data.SystemProperties, properties, p => p.GroupSequence != null, Properties.GroupSequenceName, p => p.GroupSequence); // AddIfTrue(data.SystemProperties, properties, p => p.ReplyToGroupId != null, Properties.ReplyToGroupIdName, p => p.ReplyToGroupId); //} }
public AmqpDelivery(AmqpMessage amqpMessage, ulong deliveryTag) { this.Message = amqpMessage; this.DeliveryTag = deliveryTag; }
private void OnTwinChangesReceived(AmqpMessage amqpMessage) { if (Logging.IsEnabled) { Logging.Enter(this, amqpMessage, $"{nameof(OnTwinChangesReceived)}"); } try { _receivingAmqpLink.DisposeDelivery(amqpMessage, true, AmqpIoTConstants.AcceptedOutcome); string correlationId = amqpMessage.Properties?.CorrelationId?.ToString(); int status = GetStatus(amqpMessage); Twin twin = null; TwinCollection twinProperties = null; if (status >= 400) { // Handle failures if (correlationId.StartsWith(AmqpTwinMessageType.Get.ToString(), StringComparison.OrdinalIgnoreCase) || correlationId.StartsWith(AmqpTwinMessageType.Patch.ToString(), StringComparison.OrdinalIgnoreCase)) { string error = null; using (var reader = new StreamReader(amqpMessage.BodyStream, System.Text.Encoding.UTF8)) { error = reader.ReadToEnd(); }; // Retry for Http status code request timeout, Too many requests and server errors var exception = new IotHubException(error, status >= 500 || status == 429 || status == 408); _onTwinMessageReceived.Invoke(null, correlationId, null, exception); } } else { if (correlationId == null) { // Here we are getting desired property update notifications and want to handle it first using var reader = new StreamReader(amqpMessage.BodyStream, System.Text.Encoding.UTF8); string patch = reader.ReadToEnd(); twinProperties = JsonConvert.DeserializeObject <TwinCollection>(patch); } else if (correlationId.StartsWith(AmqpTwinMessageType.Get.ToString(), StringComparison.OrdinalIgnoreCase)) { // This a response of a GET TWIN so return (set) the full twin using var reader = new StreamReader(amqpMessage.BodyStream, System.Text.Encoding.UTF8); string body = reader.ReadToEnd(); var properties = JsonConvert.DeserializeObject <TwinProperties>(body); twin = new Twin(properties); } else if (correlationId.StartsWith(AmqpTwinMessageType.Patch.ToString(), StringComparison.OrdinalIgnoreCase)) { // This can be used to coorelate success response with updating reported properties // However currently we do not have it as request response style implementation Logging.Info("Updated twin reported properties successfully", nameof(OnTwinChangesReceived)); } else if (correlationId.StartsWith(AmqpTwinMessageType.Put.ToString(), StringComparison.OrdinalIgnoreCase)) { // This is an acknowledgement received from service for subscribing to desired property updates Logging.Info("Subscribed for twin successfully", nameof(OnTwinChangesReceived)); } else { // This shouldn't happen Logging.Info("Received a correlation Id for Twin operation that does not match Get, Patch or Put request", nameof(OnTwinChangesReceived)); } _onTwinMessageReceived.Invoke(twin, correlationId, twinProperties, null); } } finally { if (Logging.IsEnabled) { Logging.Exit(this, amqpMessage, $"{nameof(OnTwinChangesReceived)}"); } } }
/// <summary> /// Sends an AMQP message that contains a batch of events to the associated Service Bus entity. If the size of events exceed the /// maximum size of a single batch, an exception will be triggered and the send will fail. /// </summary> /// /// <param name="messageFactory">A factory which can be used to produce an AMQP message containing the batch of events to be sent.</param> /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param> /// protected virtual async Task SendAsync(Func <AmqpMessage> messageFactory, CancellationToken cancellationToken) { var failedAttemptCount = 0; var stopWatch = Stopwatch.StartNew(); SendingAmqpLink link; try { var tryTimeout = RetryPolicy.CalculateTryTimeout(0); while (!cancellationToken.IsCancellationRequested) { try { using AmqpMessage batchMessage = messageFactory(); string messageHash = batchMessage.GetHashCode().ToString(); //ServiceBusEventSource.Log.EventPublishStart(EventHubName, logPartition, messageHash); link = await SendLink.GetOrCreateAsync(UseMinimum(ConnectionScope.SessionTimeout, tryTimeout)).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); // Validate that the batch of messages is not too large to send. This is done after the link is created to ensure // that the maximum message size is known, as it is dictated by the service using the link. if (batchMessage.SerializedMessageSize > MaximumMessageSize) { throw new ServiceBusException(EntityName, string.Format(Resources1.MessageSizeExceeded, messageHash, batchMessage.SerializedMessageSize, MaximumMessageSize), ServiceBusException.FailureReason.MessageSizeExceeded); } // Attempt to send the message batch. var deliveryTag = new ArraySegment <byte>(BitConverter.GetBytes(Interlocked.Increment(ref _deliveryCount))); var outcome = await link.SendMessageAsync(batchMessage, deliveryTag, AmqpConstants.NullBinary, tryTimeout.CalculateRemaining(stopWatch.Elapsed)).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); if (outcome.DescriptorCode != Accepted.Code) { throw AmqpError.CreateExceptionForError((outcome as Rejected)?.Error, EntityName); } // The send operation should be considered successful; return to // exit the retry loop. return; } catch (Exception ex) { Exception activeEx = ex.TranslateServiceException(EntityName); // Determine if there should be a retry for the next attempt; if so enforce the delay but do not quit the loop. // Otherwise, bubble the exception. ++failedAttemptCount; TimeSpan?retryDelay = RetryPolicy.CalculateRetryDelay(activeEx, failedAttemptCount); if (retryDelay.HasValue && !ConnectionScope.IsDisposed && !cancellationToken.IsCancellationRequested) { //ServiceBusEventSource.Log.EventPublishError(EventHubName, messageHash, activeEx.Message); await Task.Delay(retryDelay.Value, cancellationToken).ConfigureAwait(false); tryTimeout = RetryPolicy.CalculateTryTimeout(failedAttemptCount); stopWatch.Reset(); } else if (ex is AmqpException) { throw activeEx; } else { throw; } } } // If no value has been returned nor exception thrown by this point, // then cancellation has been requested. throw new TaskCanceledException(); } catch (Exception) { //ServiceBusEventSource.Log.EventPublishError(EventHubName, logPartition, messageHash, ex.Message); throw; } finally { stopWatch.Stop(); //ServiceBusEventSource.Log.EventPublishComplete(EventHubName, logPartition, messageHash); } }
bool OnSend(AmqpMessage message) { if (this.Link == null) { return false; } this.Link.SendDelivery(message); return true; }
public async Task SendMessageBatchTest() { // Arrange var identity = Mock.Of <IIdentity>(i => i.Id == "d1"); var amqpAuth = new AmqpAuthentication(true, Option.Some(Mock.Of <IClientCredentials>(c => c.Identity == identity))); IEnumerable <IMessage> receivedMessages = null; var deviceListener = Mock.Of <IDeviceListener>(); Mock.Get(deviceListener).Setup(d => d.ProcessDeviceMessageBatchAsync(It.IsAny <IEnumerable <IMessage> >())) .Callback <IEnumerable <IMessage> >(m => receivedMessages = m) .Returns(Task.CompletedTask); var connectionHandler = Mock.Of <IConnectionHandler>(c => c.GetAmqpAuthentication() == Task.FromResult(amqpAuth) && c.GetDeviceListener() == Task.FromResult(deviceListener)); var amqpConnection = Mock.Of <IAmqpConnection>(c => c.FindExtension <IConnectionHandler>() == connectionHandler); var amqpSession = Mock.Of <IAmqpSession>(s => s.Connection == amqpConnection); var amqpLink = Mock.Of <IReceivingAmqpLink>(l => l.Session == amqpSession && l.IsReceiver && l.Settings == new AmqpLinkSettings() && l.State == AmqpObjectState.Opened); Action <AmqpMessage> onMessageCallback = null; Mock.Get(amqpLink).Setup(l => l.RegisterMessageListener(It.IsAny <Action <AmqpMessage> >())).Callback <Action <AmqpMessage> >(a => onMessageCallback = a); Mock.Get(amqpLink).SetupGet(l => l.Settings).Returns(new AmqpLinkSettings()); Mock.Get(amqpLink).Setup(l => l.SafeAddClosed(It.IsAny <EventHandler>())); var requestUri = new Uri("amqps://foo.bar/devices/d1/messages/events"); var boundVariables = new Dictionary <string, string> { { "deviceid", "d1" } }; var messageConverter = new AmqpMessageConverter(); string content1 = "Message1 Contents ABC"; string content2 = "Message2 Contents PQR"; string content3 = "Message3 Contents XYZ"; var contents = new List <string> { content1, content2, content3 }; using (AmqpMessage amqpMessage = GetBatchedMessage(contents)) { amqpMessage.MessageFormat = AmqpConstants.AmqpBatchedMessageFormat; ILinkHandler linkHandler = new EventsLinkHandler(amqpLink, requestUri, boundVariables, messageConverter); // Act await linkHandler.OpenAsync(TimeSpan.FromSeconds(30)); // Assert Assert.NotNull(onMessageCallback); // Act onMessageCallback.Invoke(amqpMessage); // Assert await WaitAndAssert( () => { if (receivedMessages == null) { return(false); } IList <IMessage> receivedMessagesList = receivedMessages.ToList(); Assert.Equal(contents.Count, receivedMessagesList.Count); for (int i = 0; i < receivedMessagesList.Count; i++) { IMessage receivedMessage = receivedMessagesList[i]; string actualContents = Encoding.UTF8.GetString(receivedMessage.Body); Assert.Equal(contents[i], actualContents); Assert.Equal($"{i}", receivedMessage.SystemProperties[SystemProperties.MessageId]); Assert.Equal($"{i}", receivedMessage.Properties["MsgCnt"]); Assert.Equal(contents[i], receivedMessage.Properties["MsgData"]); } return(true); }, TimeSpan.FromSeconds(5)); } }
public BrokerMessage(AmqpMessage message) { this.stream = (BufferListStream)message.ToStream(); foreach (var buffer in message.RawByteBuffers) buffer.Clone(); this.RawByteBuffers = message.RawByteBuffers; }
public async Task SendMessageTest() { // Arrange var identity = Mock.Of <IIdentity>(i => i.Id == "d1"); var amqpAuth = new AmqpAuthentication(true, Option.Some(Mock.Of <IClientCredentials>(c => c.Identity == identity))); IEnumerable <IMessage> receivedMessages = null; var deviceListener = Mock.Of <IDeviceListener>(); Mock.Get(deviceListener).Setup(d => d.ProcessDeviceMessageBatchAsync(It.IsAny <IEnumerable <IMessage> >())).Callback <IEnumerable <IMessage> >(m => receivedMessages = m); var connectionHandler = Mock.Of <IConnectionHandler>(c => c.GetAmqpAuthentication() == Task.FromResult(amqpAuth) && c.GetDeviceListener() == Task.FromResult(deviceListener)); var amqpConnection = Mock.Of <IAmqpConnection>(c => c.FindExtension <IConnectionHandler>() == connectionHandler); var amqpSession = Mock.Of <IAmqpSession>(s => s.Connection == amqpConnection); var amqpLink = Mock.Of <IReceivingAmqpLink>(l => l.Session == amqpSession && l.IsReceiver && l.Settings == new AmqpLinkSettings() && l.State == AmqpObjectState.Opened); Action <AmqpMessage> onMessageCallback = null; Mock.Get(amqpLink).Setup(l => l.RegisterMessageListener(It.IsAny <Action <AmqpMessage> >())).Callback <Action <AmqpMessage> >(a => onMessageCallback = a); Mock.Get(amqpLink).SetupGet(l => l.Settings).Returns(new AmqpLinkSettings()); Mock.Get(amqpLink).Setup(l => l.SafeAddClosed(It.IsAny <EventHandler>())); var requestUri = new Uri("amqps://foo.bar/devices/d1/messages/events"); var boundVariables = new Dictionary <string, string> { { "deviceid", "d1" } }; var messageConverter = new AmqpMessageConverter(); using (AmqpMessage amqpMessage = AmqpMessage.Create(new MemoryStream(new byte[] { 1, 2, 3, 4 }), false)) { amqpMessage.ApplicationProperties.Map["Prop1"] = "Value1"; amqpMessage.ApplicationProperties.Map["Prop2"] = "Value2"; amqpMessage.Properties.ContentType = "application/json"; amqpMessage.Properties.ContentEncoding = "utf-8"; ILinkHandler linkHandler = new EventsLinkHandler(amqpLink, requestUri, boundVariables, messageConverter); // Act await linkHandler.OpenAsync(TimeSpan.FromSeconds(30)); // Assert Assert.NotNull(onMessageCallback); // Act onMessageCallback.Invoke(amqpMessage); // Assert await WaitAndAssert( () => { if (receivedMessages == null) { return(false); } IList <IMessage> receivedMessagesList = receivedMessages.ToList(); Assert.Equal(1, receivedMessagesList.Count); Assert.Equal(receivedMessagesList[0].Properties["Prop1"], "Value1"); Assert.Equal(receivedMessagesList[0].Properties["Prop2"], "Value2"); Assert.Equal(receivedMessagesList[0].SystemProperties[SystemProperties.ContentEncoding], "utf-8"); Assert.Equal(receivedMessagesList[0].SystemProperties[SystemProperties.ContentType], "application/json"); Assert.Equal(receivedMessagesList[0].SystemProperties[SystemProperties.ConnectionDeviceId], "d1"); Assert.Equal(receivedMessagesList[0].Body, new byte[] { 1, 2, 3, 4 }); return(true); }, TimeSpan.FromSeconds(5)); } }
void OnMessage(AmqpMessage message) { Outcome outcome; if (message.ValueBody.Value is Declare) { int txnId = this.CreateTransaction(); outcome = new Declared() { TxnId = new ArraySegment<byte>(BitConverter.GetBytes(txnId)) }; } else if (message.ValueBody.Value is Discharge) { Discharge discharge = (Discharge)message.ValueBody.Value; int txnId = BitConverter.ToInt32(discharge.TxnId.Array, discharge.TxnId.Offset); Transaction txn; if (this.transactions.TryGetValue(txnId, out txn)) { lock (this.transactions) { this.transactions.Remove(txnId); } txn.Discharge(discharge.Fail ?? false); outcome = AmqpConstants.AcceptedOutcome; } else { outcome = new Rejected() { Error = new Error() { Condition = AmqpErrorCode.NotFound } }; } } else { outcome = new Rejected() { Error = new Error() { Condition = AmqpErrorCode.NotAllowed } }; } message.Link.DisposeDelivery(message, true, outcome); }
/// <summary> /// Sends an AMQP message that contains a batch of events to the associated Event Hub. If the size of events exceed the /// maximum size of a single batch, an exception will be triggered and the send will fail. /// </summary> /// /// <param name="messageFactory">A factory which can be used to produce an AMQP message containing the batch of events to be sent.</param> /// <param name="partitionKey">The hashing key to use for influencing the partition to which events should be routed.</param> /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param> /// protected virtual async Task SendAsync(Func <AmqpMessage> messageFactory, string partitionKey, CancellationToken cancellationToken) { var failedAttemptCount = 0; var logPartition = PartitionId ?? partitionKey; var operationId = Guid.NewGuid().ToString("D", CultureInfo.InvariantCulture); var stopWatch = ValueStopwatch.StartNew(); TimeSpan? retryDelay; SendingAmqpLink link; try { var tryTimeout = RetryPolicy.CalculateTryTimeout(0); while (!cancellationToken.IsCancellationRequested) { try { using AmqpMessage batchMessage = messageFactory(); // Creation of the link happens without explicit knowledge of the cancellation token // used for this operation; validate the token state before attempting link creation and // again after the operation completes to provide best efforts in respecting it. EventHubsEventSource.Log.EventPublishStart(EventHubName, logPartition, operationId); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); link = await SendLink.GetOrCreateAsync(UseMinimum(ConnectionScope.SessionTimeout, tryTimeout)).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); // Validate that the batch of messages is not too large to send. This is done after the link is created to ensure // that the maximum message size is known, as it is dictated by the service using the link. if (batchMessage.SerializedMessageSize > MaximumMessageSize) { throw new EventHubsException(EventHubName, string.Format(CultureInfo.CurrentCulture, Resources.MessageSizeExceeded, operationId, batchMessage.SerializedMessageSize, MaximumMessageSize), EventHubsException.FailureReason.MessageSizeExceeded); } // Attempt to send the message batch. var deliveryTag = new ArraySegment <byte>(BitConverter.GetBytes(Interlocked.Increment(ref _deliveryCount))); var outcome = await link.SendMessageAsync(batchMessage, deliveryTag, AmqpConstants.NullBinary, tryTimeout.CalculateRemaining(stopWatch.GetElapsedTime())).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); if (outcome.DescriptorCode != Accepted.Code) { throw AmqpError.CreateExceptionForError((outcome as Rejected)?.Error, EventHubName); } // The send operation should be considered successful; return to // exit the retry loop. return; } catch (Exception ex) { Exception activeEx = ex.TranslateServiceException(EventHubName); // Determine if there should be a retry for the next attempt; if so enforce the delay but do not quit the loop. // Otherwise, bubble the exception. ++failedAttemptCount; retryDelay = RetryPolicy.CalculateRetryDelay(activeEx, failedAttemptCount); if ((retryDelay.HasValue) && (!ConnectionScope.IsDisposed) && (!cancellationToken.IsCancellationRequested)) { EventHubsEventSource.Log.EventPublishError(EventHubName, logPartition, operationId, activeEx.Message); await Task.Delay(retryDelay.Value, cancellationToken).ConfigureAwait(false); tryTimeout = RetryPolicy.CalculateTryTimeout(failedAttemptCount); stopWatch = ValueStopwatch.StartNew(); } else if (ex is AmqpException) { ExceptionDispatchInfo.Capture(activeEx).Throw(); } else { throw; } } } // If no value has been returned nor exception thrown by this point, // then cancellation has been requested. throw new TaskCanceledException(); } catch (TaskCanceledException) { throw; } catch (Exception ex) { EventHubsEventSource.Log.EventPublishError(EventHubName, logPartition, operationId, ex.Message); throw; } finally { EventHubsEventSource.Log.EventPublishComplete(EventHubName, logPartition, operationId, failedAttemptCount); } }
public void AcceptMessage(AmqpMessage message, bool settled, bool batchable) { this.DisposeMessage(message, AmqpConstants.AcceptedOutcome, settled, batchable); }
public static ServiceBusReceivedMessage AmqpMessageToSBMessage(AmqpMessage amqpMessage, bool isPeeked = false) { Argument.AssertNotNull(amqpMessage, nameof(amqpMessage)); AmqpAnnotatedMessage annotatedMessage; if ((amqpMessage.BodyType & SectionFlag.Data) != 0 && amqpMessage.DataBody != null) { annotatedMessage = new AmqpAnnotatedMessage(amqpMessage.GetDataViaDataBody()); } else { annotatedMessage = new AmqpAnnotatedMessage(new BinaryData[] { new BinaryData(Array.Empty <byte>()) }); } ServiceBusReceivedMessage sbMessage = new ServiceBusReceivedMessage(annotatedMessage); SectionFlag sections = amqpMessage.Sections; if ((sections & SectionFlag.Header) != 0) { if (amqpMessage.Header.Ttl != null) { annotatedMessage.Header.TimeToLive = TimeSpan.FromMilliseconds(amqpMessage.Header.Ttl.Value); } if (amqpMessage.Header.DeliveryCount != null) { annotatedMessage.Header.DeliveryCount = isPeeked ? (amqpMessage.Header.DeliveryCount.Value) : (amqpMessage.Header.DeliveryCount.Value + 1); } } if ((sections & SectionFlag.Properties) != 0) { if (amqpMessage.Properties.MessageId != null) { annotatedMessage.Properties.MessageId = amqpMessage.Properties.MessageId.ToString(); } if (amqpMessage.Properties.CorrelationId != null) { annotatedMessage.Properties.CorrelationId = amqpMessage.Properties.CorrelationId.ToString(); } if (amqpMessage.Properties.ContentType.Value != null) { annotatedMessage.Properties.ContentType = amqpMessage.Properties.ContentType.Value; } if (amqpMessage.Properties.Subject != null) { annotatedMessage.Properties.Subject = amqpMessage.Properties.Subject; } if (amqpMessage.Properties.To != null) { annotatedMessage.Properties.To = amqpMessage.Properties.To.ToString(); } if (amqpMessage.Properties.ReplyTo != null) { annotatedMessage.Properties.ReplyTo = amqpMessage.Properties.ReplyTo.ToString(); } if (amqpMessage.Properties.GroupId != null) { annotatedMessage.Properties.GroupId = amqpMessage.Properties.GroupId; } if (amqpMessage.Properties.ReplyToGroupId != null) { annotatedMessage.Properties.ReplyToGroupId = amqpMessage.Properties.ReplyToGroupId; } } // Do application properties before message annotations, because the application properties // can be updated by entries from message annotation. if ((sections & SectionFlag.ApplicationProperties) != 0) { foreach (var pair in amqpMessage.ApplicationProperties.Map) { if (TryGetNetObjectFromAmqpObject(pair.Value, MappingType.ApplicationProperty, out var netObject)) { annotatedMessage.ApplicationProperties[pair.Key.ToString()] = netObject; } } } if ((sections & SectionFlag.MessageAnnotations) != 0) { foreach (var pair in amqpMessage.MessageAnnotations.Map) { var key = pair.Key.ToString(); switch (key) { case AmqpMessageConstants.EnqueuedTimeUtcName: annotatedMessage.MessageAnnotations[AmqpMessageConstants.EnqueuedTimeUtcName] = (DateTime)pair.Value; break; case AmqpMessageConstants.ScheduledEnqueueTimeUtcName: annotatedMessage.MessageAnnotations[AmqpMessageConstants.ScheduledEnqueueTimeUtcName] = (DateTime)pair.Value; break; case AmqpMessageConstants.SequenceNumberName: annotatedMessage.MessageAnnotations[AmqpMessageConstants.SequenceNumberName] = (long)pair.Value; break; case AmqpMessageConstants.EnqueueSequenceNumberName: annotatedMessage.MessageAnnotations[AmqpMessageConstants.EnqueueSequenceNumberName] = (long)pair.Value; break; case AmqpMessageConstants.LockedUntilName: DateTimeOffset lockedUntil = (DateTime)pair.Value >= DateTimeOffset.MaxValue.UtcDateTime ? DateTimeOffset.MaxValue : (DateTime)pair.Value; annotatedMessage.MessageAnnotations[AmqpMessageConstants.LockedUntilName] = lockedUntil.UtcDateTime; break; case AmqpMessageConstants.PartitionKeyName: annotatedMessage.MessageAnnotations[AmqpMessageConstants.PartitionKeyName] = (string)pair.Value; break; case AmqpMessageConstants.PartitionIdName: annotatedMessage.MessageAnnotations[AmqpMessageConstants.PartitionIdName] = (short)pair.Value; break; case AmqpMessageConstants.ViaPartitionKeyName: annotatedMessage.MessageAnnotations[AmqpMessageConstants.ViaPartitionKeyName] = (string)pair.Value; break; case AmqpMessageConstants.DeadLetterSourceName: annotatedMessage.MessageAnnotations[AmqpMessageConstants.DeadLetterSourceName] = (string)pair.Value; break; default: if (TryGetNetObjectFromAmqpObject(pair.Value, MappingType.ApplicationProperty, out var netObject)) { annotatedMessage.MessageAnnotations[key] = netObject; } break; } } } if (amqpMessage.DeliveryTag.Count == GuidSizeInBytes) { var guidBuffer = new byte[GuidSizeInBytes]; Buffer.BlockCopy(amqpMessage.DeliveryTag.Array, amqpMessage.DeliveryTag.Offset, guidBuffer, 0, GuidSizeInBytes); sbMessage.LockTokenGuid = new Guid(guidBuffer); } amqpMessage.Dispose(); return(sbMessage); }
public void ReleaseMessage(AmqpMessage message) { this.DisposeMessage(message, AmqpConstants.ReleasedOutcome, true, false); }
AmqpMessage PopulateAmqpMessageForSend(AmqpMessage message) { MessageConverter.UpdateAmqpMessageHeadersAndProperties(message, this); return(message); }
public void DisposeMessage(AmqpMessage message, DeliveryState state, bool settled, bool batchable) { message.Batchable = batchable; this.DisposeDelivery(message, settled, state); }
public static AmqpMessage SBMessageToAmqpMessage(SBMessage sbMessage) { var amqpMessage = sbMessage.Body == null?AmqpMessage.Create() : AmqpMessage.Create(new Data { Value = new ArraySegment <byte>(sbMessage.Body) }); amqpMessage.Properties.MessageId = sbMessage.MessageId; amqpMessage.Properties.CorrelationId = sbMessage.CorrelationId; amqpMessage.Properties.ContentType = sbMessage.ContentType; amqpMessage.Properties.Subject = sbMessage.Label; amqpMessage.Properties.To = sbMessage.To; amqpMessage.Properties.ReplyTo = sbMessage.ReplyTo; amqpMessage.Properties.GroupId = sbMessage.SessionId; amqpMessage.Properties.ReplyToGroupId = sbMessage.ReplyToSessionId; if (sbMessage.TimeToLive != TimeSpan.MaxValue) { amqpMessage.Header.Ttl = (uint)sbMessage.TimeToLive.TotalMilliseconds; amqpMessage.Properties.CreationTime = DateTime.UtcNow; if (AmqpConstants.MaxAbsoluteExpiryTime - amqpMessage.Properties.CreationTime.Value > sbMessage.TimeToLive) { amqpMessage.Properties.AbsoluteExpiryTime = amqpMessage.Properties.CreationTime.Value + sbMessage.TimeToLive; } else { amqpMessage.Properties.AbsoluteExpiryTime = AmqpConstants.MaxAbsoluteExpiryTime; } } if ((sbMessage.ScheduledEnqueueTimeUtc != null) && sbMessage.ScheduledEnqueueTimeUtc > DateTime.MinValue) { amqpMessage.MessageAnnotations.Map.Add(ScheduledEnqueueTimeUtcName, sbMessage.ScheduledEnqueueTimeUtc); } if (sbMessage.PartitionKey != null) { amqpMessage.MessageAnnotations.Map.Add(PartitionKeyName, sbMessage.PartitionKey); } if (sbMessage.ViaPartitionKey != null) { amqpMessage.MessageAnnotations.Map.Add(ViaPartitionKeyName, sbMessage.ViaPartitionKey); } if (sbMessage.UserProperties != null && sbMessage.UserProperties.Count > 0) { if (amqpMessage.ApplicationProperties == null) { amqpMessage.ApplicationProperties = new ApplicationProperties(); } foreach (var pair in sbMessage.UserProperties) { if (TryGetAmqpObjectFromNetObject(pair.Value, MappingType.ApplicationProperty, out var amqpObject)) { amqpMessage.ApplicationProperties.Map.Add(pair.Key, amqpObject); } else { throw new NotSupportedException(Resources.InvalidAmqpMessageProperty.FormatForUser(pair.Key.GetType())); } } } return(amqpMessage); }
public void Signal(AmqpMessage message, bool syncComplete) { IOThreadTimer t = this.timer; if (t != null) { t.Cancel(); } this.CompleteInternal(message, syncComplete); }
public static SBMessage AmqpMessageToSBMessage(AmqpMessage amqpMessage) { if (amqpMessage == null) { throw Fx.Exception.ArgumentNull(nameof(amqpMessage)); } SBMessage sbMessage; if ((amqpMessage.BodyType & SectionFlag.AmqpValue) != 0 && amqpMessage.ValueBody.Value != null) { sbMessage = new SBMessage(); if (TryGetNetObjectFromAmqpObject(amqpMessage.ValueBody.Value, MappingType.MessageBody, out var dotNetObject)) { sbMessage.SystemProperties.BodyObject = dotNetObject; } else { sbMessage.SystemProperties.BodyObject = amqpMessage.ValueBody.Value; } } else if ((amqpMessage.BodyType & SectionFlag.Data) != 0 && amqpMessage.DataBody != null) { var dataSegments = new List <byte>(); foreach (var data in amqpMessage.DataBody) { if (data.Value is byte[] byteArrayValue) { dataSegments.AddRange(byteArrayValue); } else if (data.Value is ArraySegment <byte> arraySegmentValue) { byte[] byteArray; if (arraySegmentValue.Count == arraySegmentValue.Array.Length) { byteArray = arraySegmentValue.Array; } else { byteArray = new byte[arraySegmentValue.Count]; Array.ConstrainedCopy(arraySegmentValue.Array, arraySegmentValue.Offset, byteArray, 0, arraySegmentValue.Count); } dataSegments.AddRange(byteArray); } } sbMessage = new SBMessage(dataSegments.ToArray()); } else { sbMessage = new SBMessage(); } var sections = amqpMessage.Sections; if ((sections & SectionFlag.Header) != 0) { if (amqpMessage.Header.Ttl != null) { sbMessage.TimeToLive = TimeSpan.FromMilliseconds(amqpMessage.Header.Ttl.Value); } if (amqpMessage.Header.DeliveryCount != null) { sbMessage.SystemProperties.DeliveryCount = (int)(amqpMessage.Header.DeliveryCount.Value + 1); } } if ((sections & SectionFlag.Properties) != 0) { if (amqpMessage.Properties.MessageId != null) { sbMessage.MessageId = amqpMessage.Properties.MessageId.ToString(); } if (amqpMessage.Properties.CorrelationId != null) { sbMessage.CorrelationId = amqpMessage.Properties.CorrelationId.ToString(); } if (amqpMessage.Properties.ContentType.Value != null) { sbMessage.ContentType = amqpMessage.Properties.ContentType.Value; } if (amqpMessage.Properties.Subject != null) { sbMessage.Label = amqpMessage.Properties.Subject; } if (amqpMessage.Properties.To != null) { sbMessage.To = amqpMessage.Properties.To.ToString(); } if (amqpMessage.Properties.ReplyTo != null) { sbMessage.ReplyTo = amqpMessage.Properties.ReplyTo.ToString(); } if (amqpMessage.Properties.GroupId != null) { sbMessage.SessionId = amqpMessage.Properties.GroupId; } if (amqpMessage.Properties.ReplyToGroupId != null) { sbMessage.ReplyToSessionId = amqpMessage.Properties.ReplyToGroupId; } } // Do application properties before message annotations, because the application properties // can be updated by entries from message annotation. if ((sections & SectionFlag.ApplicationProperties) != 0) { foreach (var pair in amqpMessage.ApplicationProperties.Map) { if (TryGetNetObjectFromAmqpObject(pair.Value, MappingType.ApplicationProperty, out var netObject)) { sbMessage.UserProperties[pair.Key.ToString()] = netObject; } } } if ((sections & SectionFlag.MessageAnnotations) != 0) { foreach (var pair in amqpMessage.MessageAnnotations.Map) { var key = pair.Key.ToString(); switch (key) { case EnqueuedTimeUtcName: sbMessage.SystemProperties.EnqueuedTimeUtc = (DateTime)pair.Value; break; case ScheduledEnqueueTimeUtcName: sbMessage.ScheduledEnqueueTimeUtc = (DateTime)pair.Value; break; case SequenceNumberName: sbMessage.SystemProperties.SequenceNumber = (long)pair.Value; break; case EnqueueSequenceNumberName: sbMessage.SystemProperties.EnqueuedSequenceNumber = (long)pair.Value; break; case LockedUntilName: sbMessage.SystemProperties.LockedUntilUtc = (DateTime)pair.Value; break; case PartitionKeyName: sbMessage.PartitionKey = (string)pair.Value; break; case PartitionIdName: sbMessage.SystemProperties.PartitionId = (short)pair.Value; break; case ViaPartitionKeyName: sbMessage.ViaPartitionKey = (string)pair.Value; break; case DeadLetterSourceName: sbMessage.SystemProperties.DeadLetterSource = (string)pair.Value; break; default: if (TryGetNetObjectFromAmqpObject(pair.Value, MappingType.ApplicationProperty, out var netObject)) { sbMessage.UserProperties[key] = netObject; } break; } } } if (amqpMessage.DeliveryTag.Count == GuidSize) { var guidBuffer = new byte[GuidSize]; Buffer.BlockCopy(amqpMessage.DeliveryTag.Array, amqpMessage.DeliveryTag.Offset, guidBuffer, 0, GuidSize); sbMessage.SystemProperties.LockTokenGuid = new Guid(guidBuffer); } amqpMessage.Dispose(); return(sbMessage); }
public Task<Outcome> SendMessageAsync(AmqpMessage message, ArraySegment<byte> deliveryTag, ArraySegment<byte> txnId, TimeSpan timeout) { return this.sender.SendMessageAsync(message, deliveryTag, txnId, timeout); }
public static AmqpMessage BatchSBMessagesAsAmqpMessage(IEnumerable <SBMessage> sbMessages) { if (sbMessages == null) { throw Fx.Exception.ArgumentNull(nameof(sbMessages)); } AmqpMessage amqpMessage; AmqpMessage firstAmqpMessage = null; SBMessage firstMessage = null; List <Data> dataList = null; var messageCount = 0; foreach (var sbMessage in sbMessages) { messageCount++; amqpMessage = AmqpMessageConverter.SBMessageToAmqpMessage(sbMessage); if (firstAmqpMessage == null) { firstAmqpMessage = amqpMessage; firstMessage = sbMessage; continue; } if (dataList == null) { dataList = new List <Data> { ToData(firstAmqpMessage) }; } dataList.Add(ToData(amqpMessage)); } if (messageCount == 1 && firstAmqpMessage != null) { firstAmqpMessage.Batchable = true; return(firstAmqpMessage); } amqpMessage = AmqpMessage.Create(dataList); amqpMessage.MessageFormat = AmqpConstants.AmqpBatchedMessageFormat; if (firstMessage.MessageId != null) { amqpMessage.Properties.MessageId = firstMessage.MessageId; } if (firstMessage.SessionId != null) { amqpMessage.Properties.GroupId = firstMessage.SessionId; } if (firstMessage.PartitionKey != null) { amqpMessage.MessageAnnotations.Map[AmqpMessageConverter.PartitionKeyName] = firstMessage.PartitionKey; } if (firstMessage.ViaPartitionKey != null) { amqpMessage.MessageAnnotations.Map[AmqpMessageConverter.ViaPartitionKeyName] = firstMessage.ViaPartitionKey; } amqpMessage.Batchable = true; return(amqpMessage); }
async Task<Outcome> SendAmqpMessageAsync(AmqpMessage amqpMessage) { Outcome outcome; try { SendingAmqpLink eventSendingLink = await this.GetEventSendingLinkAsync(); outcome = await eventSendingLink.SendMessageAsync(amqpMessage, IotHubConnection.GetNextDeliveryTag(ref this.eventsDeliveryTag), AmqpConstants.NullBinary, this.OperationTimeout); } catch (Exception exception) { if (exception.IsFatal()) { throw; } throw AmqpClientHelper.ToIotHubClientContract(exception); } return outcome; }
/// <summary> /// Retrieves information about a specific partition for an Event Hub, including elements that describe the available /// events in the partition event stream. /// </summary> /// /// <param name="partitionId">The unique identifier of a partition associated with the Event Hub.</param> /// <param name="retryPolicy">The retry policy to use as the basis for retrieving the information.</param> /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param> /// /// <returns>The set of information for the requested partition under the Event Hub this client is associated with.</returns> /// public override async Task <PartitionProperties> GetPartitionPropertiesAsync(string partitionId, EventHubsRetryPolicy retryPolicy, CancellationToken cancellationToken) { Argument.AssertNotClosed(_closed, nameof(AmqpClient)); Argument.AssertNotNullOrEmpty(partitionId, nameof(partitionId)); Argument.AssertNotNull(retryPolicy, nameof(retryPolicy)); var failedAttemptCount = 0; var retryDelay = default(TimeSpan?); var token = default(string); var link = default(RequestResponseAmqpLink); var stopWatch = Stopwatch.StartNew(); try { var tryTimeout = retryPolicy.CalculateTryTimeout(0); while (!cancellationToken.IsCancellationRequested) { try { EventHubsEventSource.Log.GetPartitionPropertiesStart(EventHubName, partitionId); // Create the request message and the management link. token = await AquireAccessTokenAsync(cancellationToken).ConfigureAwait(false); using AmqpMessage request = MessageConverter.CreatePartitionPropertiesRequest(EventHubName, partitionId, token); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); link = await ManagementLink.GetOrCreateAsync(UseMinimum(ConnectionScope.SessionTimeout, tryTimeout.CalculateRemaining(stopWatch.Elapsed))).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); // Send the request and wait for the response. using AmqpMessage response = await link.RequestAsync(request, tryTimeout.CalculateRemaining(stopWatch.Elapsed)).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); stopWatch.Stop(); // Process the response. AmqpError.ThrowIfErrorResponse(response, EventHubName); return(MessageConverter.CreatePartitionPropertiesFromResponse(response)); } catch (Exception ex) { // Determine if there should be a retry for the next attempt; if so enforce the delay but do not quit the loop. // Otherwise, mark the exception as active and break out of the loop. ++failedAttemptCount; retryDelay = retryPolicy.CalculateRetryDelay(ex, failedAttemptCount); if ((retryDelay.HasValue) && (!ConnectionScope.IsDisposed) && (!cancellationToken.IsCancellationRequested)) { EventHubsEventSource.Log.GetPartitionPropertiesError(EventHubName, partitionId, ex.Message); await Task.Delay(retryDelay.Value, cancellationToken).ConfigureAwait(false); tryTimeout = retryPolicy.CalculateTryTimeout(failedAttemptCount); stopWatch.Reset(); } else { throw; } } } // If no value has been returned nor exception thrown by this point, // then cancellation has been requested. throw new TaskCanceledException(); } catch (Exception ex) { EventHubsEventSource.Log.GetPartitionPropertiesError(EventHubName, partitionId, ex.Message); throw; } finally { stopWatch.Stop(); EventHubsEventSource.Log.GetPartitionPropertiesComplete(EventHubName, partitionId); } }
/// <summary> /// Copies the properties from the amqp message to the Message instance. /// </summary> public static void UpdateMessageHeaderAndProperties(AmqpMessage amqpMessage, Message data) { Fx.AssertAndThrow(amqpMessage.DeliveryTag != null, "AmqpMessage should always contain delivery tag."); data.DeliveryTag = amqpMessage.DeliveryTag; SectionFlag sections = amqpMessage.Sections; if ((sections & SectionFlag.Properties) != 0) { // Extract only the Properties that we support data.MessageId = amqpMessage.Properties.MessageId != null ? amqpMessage.Properties.MessageId.ToString() : null; data.To = amqpMessage.Properties.To != null ? amqpMessage.Properties.To.ToString() : null; if (amqpMessage.Properties.AbsoluteExpiryTime.HasValue) { data.ExpiryTimeUtc = amqpMessage.Properties.AbsoluteExpiryTime.Value; } data.CorrelationId = amqpMessage.Properties.CorrelationId != null ? amqpMessage.Properties.CorrelationId.ToString() : null; data.UserId = amqpMessage.Properties.UserId.Array != null ? Encoding.UTF8.GetString(amqpMessage.Properties.UserId.Array) : null; } if ((sections & SectionFlag.MessageAnnotations) != 0) { string lockToken; if (amqpMessage.MessageAnnotations.Map.TryGetValue(LockTokenName, out lockToken)) { data.LockToken = lockToken; } ulong sequenceNumber; if (amqpMessage.MessageAnnotations.Map.TryGetValue(SequenceNumberName, out sequenceNumber)) { data.SequenceNumber = sequenceNumber; } DateTime enqueuedTime; if (amqpMessage.MessageAnnotations.Map.TryGetValue(MessageSystemPropertyNames.EnqueuedTime, out enqueuedTime)) { data.EnqueuedTimeUtc = enqueuedTime; } byte deliveryCount; if (amqpMessage.MessageAnnotations.Map.TryGetValue(MessageSystemPropertyNames.DeliveryCount, out deliveryCount)) { data.DeliveryCount = deliveryCount; } } if ((sections & SectionFlag.ApplicationProperties) != 0) { foreach (KeyValuePair<MapKey, object> pair in amqpMessage.ApplicationProperties.Map) { object netObject = null; if (TryGetNetObjectFromAmqpObject(pair.Value, MappingType.ApplicationProperty, out netObject)) { var stringObject = netObject as string; if (stringObject != null) { switch (pair.Key.ToString()) { case MessageSystemPropertyNames.Operation: data.SystemProperties[pair.Key.ToString()] = stringObject; break; default: data.Properties[pair.Key.ToString()] = stringObject; break; } } else { // TODO: RDBug 4093369 Handling of non-string property values in Amqp messages // Drop non-string properties and log an error Fx.Exception.TraceHandled(new InvalidDataException("IotHub does not accept non-string Amqp properties"), "MessageConverter.UpdateMessageHeaderAndProperties"); } } } } }
protected override async Task OnSendAsync(IEnumerable <EventData> eventDatas, string partitionKey) { bool shouldRetry; int retryCount = 0; var timeoutHelper = new TimeoutHelper(this.EventHubClient.ConnectionStringBuilder.OperationTimeout, startTimeout: true); do { using (AmqpMessage amqpMessage = AmqpMessageConverter.EventDatasToAmqpMessage(eventDatas, partitionKey)) { shouldRetry = false; try { try { // Always use default timeout for AMQP sesssion. var amqpLink = await this.SendLinkManager.GetOrCreateAsync( TimeSpan.FromSeconds(AmqpClientConstants.AmqpSessionTimeoutInSeconds)).ConfigureAwait(false); if (amqpLink.Settings.MaxMessageSize.HasValue) { ulong size = (ulong)amqpMessage.SerializedMessageSize; if (size > amqpLink.Settings.MaxMessageSize.Value) { throw new MessageSizeExceededException(amqpMessage.DeliveryId.Value, size, amqpLink.Settings.MaxMessageSize.Value); } } Outcome outcome = await amqpLink.SendMessageAsync( amqpMessage, this.GetNextDeliveryTag(), AmqpConstants.NullBinary, timeoutHelper.RemainingTime()).ConfigureAwait(false); if (outcome.DescriptorCode != Accepted.Code) { Rejected rejected = (Rejected)outcome; throw new AmqpException(rejected.Error); } } catch (AmqpException amqpException) { throw AmqpExceptionHelper.ToMessagingContract(amqpException.Error); } } catch (Exception ex) { // Evaluate retry condition? TimeSpan?retryInterval = this.RetryPolicy.GetNextRetryInterval(ex, timeoutHelper.RemainingTime(), ++retryCount); if (retryInterval != null && !this.EventHubClient.CloseCalled) { await Task.Delay(retryInterval.Value).ConfigureAwait(false); shouldRetry = true; } else { throw; } } } } while (shouldRetry); }