async Task AcknowledgePublishAsync(IChannelHandlerContext context, AckPendingMessageState message) { this.ResumeReadingIfNecessary(context); // todo: is try-catch needed here? try { await message.FeedbackChannel.CompleteAsync(); PerformanceCounters.OutboundMessageProcessingTime.Register(message.StartTimestamp); this.publishPubAckProcessor.ResumeRetransmission(context); } catch (Exception ex) { ShutdownOnError(context, "-> PUBACK", ex); } }
async Task AcknowledgePublishReceiveAsync(IChannelHandlerContext context, AckPendingMessageState message) { this.ResumeReadingIfNecessary(context); // todo: is try-catch needed here? try { IQos2MessageDeliveryState messageInfo = this.qos2StateProvider.Create(message.SequenceNumber); await this.qos2StateProvider.SetMessageAsync(this.identity, message.PacketId, messageInfo); await this.PublishReleaseToClientAsync(context, message.PacketId, message.FeedbackChannel, messageInfo, message.StartTimestamp); this.publishPubRecProcessor.ResumeRetransmission(context); } catch (Exception ex) { ShutdownOnError(context, "-> PUBREC", ex); } }
async void RetransmitNextPublish(IChannelHandlerContext context, AckPendingMessageState messageInfo) { bool wasReceiving = this.IsInState(StateFlags.Receiving); try { await this.messagingServiceClient.AbandonAsync(messageInfo.LockToken); if (!wasReceiving) { this.Receive(context); } } catch (MessagingException ex) { this.ShutdownOnReceiveError(context, ex.ToString()); } catch (Exception ex) { ShutdownOnError(context, ex.ToString()); } }
async Task AcknowledgePublishAsync(IChannelHandlerContext context, AckPendingMessageState message) { this.ResumeReadingIfNecessary(context); // todo: is try-catch needed here? try { await this.messagingServiceClient.CompleteAsync(message.LockToken); PerformanceCounters.OutboundMessageProcessingTime.Register(message.StartTimestamp); if (this.publishPubAckProcessor.ResumeRetransmission(context)) { return; } this.RestartReceiveIfPossible(context); } catch (Exception ex) { ShutdownOnError(context, "-> PUBACK", ex); } }
async void RetransmitPublishMessage(IChannelHandlerContext context, IMessage message, AckPendingMessageState messageInfo) { try { using (message) { string topicName; message.Properties[TemplateParameters.DeviceIdTemplateParam] = this.DeviceId; if (!this.messageRouter.TryRouteOutgoingMessage(RouteSourceType.Notification, message, out topicName)) { throw new InvalidOperationException("Route mapping failed on retransmission."); } PublishPacket packet = await Util.ComposePublishPacketAsync(context, message, messageInfo.QualityOfService, topicName, context.Channel.Allocator); messageInfo.ResetMessage(message); await this.publishPubAckProcessor.RetransmitAsync(context, packet, messageInfo); } } catch (Exception ex) { // todo: log more details ShutdownOnError(context, "<- PUBLISH (retransmission)", ex); } }
async void Receive(IChannelHandlerContext context) { try { IMessage message = await this.messagingServiceClient.ReceiveAsync(); if (message == null) { // link to IoT Hub has been closed this.ShutdownOnReceiveError(context, null); return; } PerformanceCounters.MessagesReceivedPerSecond.Increment(); bool receiving = this.IsInState(StateFlags.Receiving); int processorsInRetransmission = 0; bool messageSent = false; if (this.publishPubAckProcessor.Retransmitting) { processorsInRetransmission++; AckPendingMessageState pendingPubAck = this.publishPubAckProcessor.FirstRequestPendingAck; if (pendingPubAck.SequenceNumber == message.SequenceNumber) { this.RetransmitPublishMessage(context, message, pendingPubAck); messageSent = true; } } if (this.publishPubRecProcessor.Retransmitting) { processorsInRetransmission++; if (!messageSent) { AckPendingMessageState pendingPubRec = this.publishPubRecProcessor.FirstRequestPendingAck; if (pendingPubRec.SequenceNumber == message.SequenceNumber) { this.RetransmitPublishMessage(context, message, pendingPubRec); messageSent = true; } } } if (processorsInRetransmission == 0) { this.PublishToClientAsync(context, message).OnFault(ShutdownOnPublishFaultAction, context); if (!this.IsInState(StateFlags.Closed) && (this.MessagePendingAckCount < this.settings.MaxPendingOutboundMessages)) { this.Receive(context); // todo: review for potential stack depth issues } else { this.ResetState(StateFlags.Receiving); } } else { if (receiving) { if (!messageSent) { // message id is different - "publish" this message (it actually will be enqueued for future retransmission immediately) await this.PublishToClientAsync(context, message); } this.ResetState(StateFlags.Receiving); for (int i = processorsInRetransmission - (messageSent ? 1 : 0); i > 0; i--) { // fire receive for processors that went into retransmission but held off receiving messages due to ongoing receive call this.Receive(context); // todo: review for potential stack depth issues } } else if (!messageSent) { throw new InvalidOperationException("Received a message that does not match"); } } } catch (MessagingException ex) { this.ShutdownOnReceiveError(context, ex.ToString()); } catch (Exception ex) { ShutdownOnError(context, "Receive", ex.ToString()); } }
async void RetransmitPublishMessage(IChannelHandlerContext context, MessageWithFeedback messageWithFeedback, AckPendingMessageState messageInfo) { PublishPacket packet = null; try { using (IMessage message = messageWithFeedback.Message) { message.Properties[TemplateParameters.DeviceIdTemplateParam] = this.DeviceId; packet = Util.ComposePublishPacket(context, message, messageInfo.QualityOfService, context.Channel.Allocator); messageInfo.ResetMessage(message, messageWithFeedback.FeedbackChannel); await this.publishPubAckProcessor.RetransmitAsync(context, packet, messageInfo); } } catch (Exception ex) { ReferenceCountUtil.SafeRelease(packet); ShutdownOnError(context, "<- PUBLISH (retransmission)", ex); } }
async void RetransmitPublishMessage(IChannelHandlerContext context, Message message, AckPendingMessageState messageInfo) { try { using (message) { string topicName; var completeContext = new ReadOnlyMergeDictionary<string, string>(this.sessionContext, message.Properties); if (!this.topicNameRouter.TryMapRouteToTopicName(RouteSourceType.Notification, completeContext, out topicName)) { throw new InvalidOperationException("Route mapping failed on retransmission."); } PublishPacket packet = await Util.ComposePublishPacketAsync(context, message, messageInfo.QualityOfService, topicName); messageInfo.ResetMessage(message); await this.publishPubAckProcessor.RetransmitAsync(context, packet, messageInfo); } } catch (Exception ex) { // todo: log more details ShutdownOnError(context, "<- PUBLISH (retransmission)", ex); } }
public async void Handle(MessageWithFeedback messageWithFeedback) { IChannelHandlerContext context = this.capturedContext; IMessage message = messageWithFeedback.Message; try { Contract.Assert(message != null); PerformanceCounters.MessagesReceivedPerSecond.Increment(); int processorsInRetransmission = 0; bool sentThroughRetransmission = false; if (this.publishPubAckProcessor.Retransmitting) { processorsInRetransmission++; AckPendingMessageState pendingPubAck = this.publishPubAckProcessor.FirstRequestPendingAck; if (pendingPubAck.SequenceNumber == message.SequenceNumber) { this.RetransmitPublishMessage(context, messageWithFeedback, pendingPubAck); sentThroughRetransmission = true; } } if (this.publishPubRecProcessor.Retransmitting) { processorsInRetransmission++; if (!sentThroughRetransmission) { AckPendingMessageState pendingPubRec = this.publishPubRecProcessor.FirstRequestPendingAck; if (pendingPubRec.SequenceNumber == message.SequenceNumber) { this.RetransmitPublishMessage(context, messageWithFeedback, pendingPubRec); sentThroughRetransmission = true; } } } if (processorsInRetransmission == 0) { this.PublishToClientAsync(context, messageWithFeedback).OnFault(ShutdownOnPublishFaultAction, context); } else { if (!sentThroughRetransmission) { // message id is different - "publish" this message (it actually will be enqueued for future retransmission immediately) await this.PublishToClientAsync(context, messageWithFeedback); // todo: consider back pressure in a form of explicit retransmission state communication with MSC } } message = null; } catch (MessagingException ex) { this.ShutdownOnReceiveError(ex); } catch (Exception ex) { ShutdownOnError(context, ReceiveProcessingScope, ex); } finally { if (message != null) { ReferenceCountUtil.SafeRelease(message.Payload); } } }
async void RetransmitNextPublish(IChannelHandlerContext context, AckPendingMessageState messageInfo) { bool wasReceiving = this.IsInState(StateFlags.Receiving); try { await this.iotHubClient.AbandonAsync(messageInfo.LockToken); if (!wasReceiving) { this.Receive(context); } } catch (IotHubException ex) { this.ShutdownOnReceiveError(context, ex.ToString()); } catch (Exception ex) { ShutdownOnError(context, ex.ToString()); } }
async Task AcknowledgePublishReceiveAsync(IChannelHandlerContext context, AckPendingMessageState message) { this.ResumeReadingIfNecessary(context); // todo: is try-catch needed here? try { IQos2MessageDeliveryState messageInfo = this.qos2StateProvider.Create(message.MessageId); await this.qos2StateProvider.SetMessageAsync(message.PacketId, messageInfo); await this.PublishReleaseToClientAsync(context, message.PacketId, message.LockToken, messageInfo, message.StartTimestamp); if (this.publishPubRecProcessor.ResumeRetransmission(context)) { return; } this.RestartReceiveIfPossible(context); } catch (Exception ex) { ShutdownOnError(context, "-> PUBREC", ex); } }
async Task AcknowledgePublishAsync(IChannelHandlerContext context, AckPendingMessageState message) { this.ResumeReadingIfNecessary(context); // todo: is try-catch needed here? try { await this.iotHubClient.CompleteAsync(message.LockToken); PerformanceCounters.OutboundMessageProcessingTime.Register(message.StartTimestamp); if (this.publishPubAckProcessor.ResumeRetransmission(context)) { return; } this.RestartReceiveIfPossible(context); } catch (Exception ex) { ShutdownOnError(context, "-> PUBACK", ex); } }
async void RetransmitPublishMessage(IChannelHandlerContext context, Message message, AckPendingMessageState messageInfo) { try { using (message) { string topicName; var completeContext = new ReadOnlyMergeDictionary <string, string>(this.sessionContext, message.Properties); if (!this.topicNameRouter.TryMapRouteToTopicName(RouteSourceType.Notification, completeContext, out topicName)) { throw new InvalidOperationException("Route mapping failed on retransmission."); } PublishPacket packet = await Util.ComposePublishPacketAsync(context, message, messageInfo.QualityOfService, topicName); messageInfo.ResetMessage(message); await this.publishPubAckProcessor.RetransmitAsync(context, packet, messageInfo); } } catch (Exception ex) { // todo: log more details ShutdownOnError(context, "<- PUBLISH (retransmission)", ex); } }
async void RetransmitPublishMessage(IChannelHandlerContext context, IMessage message, AckPendingMessageState messageInfo) { try { using (message) { string topicName; message.Properties[TemplateParameters.DeviceIdTemplateParam] = this.DeviceId; if (!this.messageRouter.TryRouteOutgoingMessage(RouteSourceType.Notification, message, out topicName)) { throw new InvalidOperationException("Route mapping failed on retransmission."); } PublishPacket packet = await Util.ComposePublishPacketAsync(context, message, messageInfo.QualityOfService, topicName, context.Channel.Allocator); messageInfo.ResetMessage(message); await this.publishPubAckProcessor.RetransmitAsync(context, packet, messageInfo); } } catch (Exception ex) { // todo: log more details ShutdownOnError(context, "<- PUBLISH (retransmission)", ex); } }