Пример #1
0
            async Task <ISinkResult <IRoutingMessage> > ProcessAsync(IRoutingMessage routingMessage, string identity)
            {
                IMessage message = this.cloudEndpoint.messageConverter.ToMessage(routingMessage);

                Util.Option <ICloudProxy> cloudProxy = await this.cloudEndpoint.cloudProxyGetterFunc(identity);

                ISinkResult result = await cloudProxy.Match(
                    async cp =>
                {
                    try
                    {
                        using (Metrics.CloudLatency(identity))
                        {
                            await cp.SendMessageAsync(message);
                        }

                        var succeeded = new List <IRoutingMessage> {
                            routingMessage
                        };
                        Metrics.MessageCount(identity);

                        return(new SinkResult <IRoutingMessage>(succeeded));
                    }
                    catch (Exception ex)
                    {
                        return(this.HandleException(ex, routingMessage));
                    }
                },
                    () => this.ProcessNoConnection(identity, routingMessage));

                return(result);
            }
Пример #2
0
            public static void DeviceIdNotFound(IRoutingMessage routingMessage)
            {
                string message = routingMessage.SystemProperties.TryGetValue(SystemProperties.MessageId, out string messageId)
                    ? Invariant($"Message with MessageId {messageId} does not contain a device Id.")
                    : "Received message does not contain a device Id";

                Log.LogError((int)EventIds.DeviceIdNotFound, message);
            }
Пример #3
0
        static void ValidateMessageSize(IRoutingMessage messageToBeValidated)
        {
            long messageSize = messageToBeValidated.Size();

            if (messageSize > MaxMessageSize)
            {
                throw new InvalidOperationException($"Message size exceeds maximum allowed size: got {messageSize}, limit {MaxMessageSize}");
            }
        }
Пример #4
0
        public Task ProcessDeviceMessage(IIdentity identity, IMessage message)
        {
            Preconditions.CheckNotNull(message, nameof(message));
            Preconditions.CheckNotNull(identity, nameof(identity));
            Events.MessageReceived(identity);
            IRoutingMessage routingMessage = this.ProcessMessageInternal(message, true);

            return(this.router.RouteAsync(routingMessage));
        }
Пример #5
0
        static void ValidateMessageSize(IRoutingMessage messageToBeValidated)
        {
            long messageSize = messageToBeValidated.Size();

            if (messageSize > MaxMessageSize)
            {
                throw new EdgeHubMessageTooLargeException($"Message size is {messageSize} bytes which is greater than the max size {MaxMessageSize} bytes allowed");
            }
        }
Пример #6
0
            Task <ISinkResult> ProcessNoConnection(string identity, IRoutingMessage routingMessage)
            {
                Events.IoTHubNotConnected(identity);
                var failed = new List <IRoutingMessage> {
                    routingMessage
                };
                var sendFailureDetails = new SendFailureDetails(FailureKind.Transient, new EdgeHubConnectionException("IoT Hub is not connected"));

                return(Task.FromResult((ISinkResult <IRoutingMessage>) new SinkResult <IRoutingMessage>(ImmutableList <IRoutingMessage> .Empty, failed, sendFailureDetails)));
            }
Пример #7
0
            Task <ISinkResult> ProcessNoIdentity(IRoutingMessage routingMessage)
            {
                Events.InvalidMessageNoIdentity();
                var invalid = new List <InvalidDetails <IRoutingMessage> > {
                    new InvalidDetails <IRoutingMessage>(routingMessage, FailureKind.InvalidInput)
                };
                var sendFailureDetails = new SendFailureDetails(FailureKind.InvalidInput, new InvalidOperationException("Message does not contain client identity"));

                return(Task.FromResult((ISinkResult <IRoutingMessage>) new SinkResult <IRoutingMessage>(ImmutableList <IRoutingMessage> .Empty, ImmutableList <IRoutingMessage> .Empty, invalid, sendFailureDetails)));
            }
Пример #8
0
            public async Task <ISinkResult> ProcessAsync(IRoutingMessage routingMessage, CancellationToken token)
            {
                Preconditions.CheckNotNull(routingMessage, nameof(routingMessage));
                var succeeded = new List <IRoutingMessage>();
                var failed    = new List <IRoutingMessage>();
                var invalid   = new List <InvalidDetails <IRoutingMessage> >();
                SendFailureDetails sendFailureDetails = null;

                IMessage message = this.cloudEndpoint.messageConverter.ToMessage(routingMessage);

                Util.Option <ICloudProxy> cloudProxy = await this.GetCloudProxy(routingMessage);

                if (!cloudProxy.HasValue)
                {
                    sendFailureDetails = new SendFailureDetails(FailureKind.None, new EdgeHubConnectionException("IoT Hub is not connected"));
                    failed.Add(routingMessage);
                }
                else
                {
                    await cloudProxy.ForEachAsync(async cp =>
                    {
                        try
                        {
                            string id = this.GetIdentity(routingMessage).Expect(() => new InvalidOperationException("Could not retrieve identity of message"));
                            using (Metrics.CloudLatency(id))
                            {
                                await cp.SendMessageAsync(message);
                            }
                            succeeded.Add(routingMessage);
                            Metrics.MessageCount(id);
                        }
                        catch (Exception ex)
                        {
                            if (IsRetryable(ex))
                            {
                                failed.Add(routingMessage);
                            }
                            else
                            {
                                Events.InvalidMessage(ex);
                                invalid.Add(new InvalidDetails <IRoutingMessage>(routingMessage, FailureKind.None));
                            }

                            if (failed.Count > 0)
                            {
                                Events.RetryingMessage(routingMessage, ex);
                                sendFailureDetails = new SendFailureDetails(FailureKind.Transient, new EdgeHubIOException($"Error sending messages to IotHub for device {this.cloudEndpoint.Id}"));
                            }
                        }
                    });
                }

                return(new SinkResult <IRoutingMessage>(succeeded, failed, invalid, sendFailureDetails));
            }
Пример #9
0
 Util.Option <string> GetIdentity(IRoutingMessage routingMessage)
 {
     if (routingMessage.SystemProperties.TryGetValue(SystemProperties.ConnectionDeviceId, out string deviceId))
     {
         return(Option.Some(routingMessage.SystemProperties.TryGetValue(SystemProperties.ConnectionModuleId, out string moduleId)
             ? $"{deviceId}/{moduleId}"
             : deviceId));
     }
     Events.DeviceIdNotFound(routingMessage);
     return(Option.None <string>());
 }
Пример #10
0
            public async Task <ISinkResult> ProcessAsync(IRoutingMessage routingMessage, CancellationToken token)
            {
                Preconditions.CheckNotNull(routingMessage, nameof(routingMessage));

                string      id     = this.GetIdentity(routingMessage);
                ISinkResult result = await this.ProcessClientMessagesBatch(id, new List <IRoutingMessage> {
                    routingMessage
                }, token);

                Events.DoneProcessing(token);
                return(result);
            }
Пример #11
0
 public static void CancelledProcessingMessages(ICollection <IRoutingMessage> messages)
 {
     if (messages.Count > 0)
     {
         IRoutingMessage firstMessage = messages.OrderBy(m => m.Offset).First();
         Log.LogDebug((int)EventIds.CancelledProcessing, $"Cancelled sending messages from offset {firstMessage.Offset}");
     }
     else
     {
         Log.LogDebug((int)EventIds.CancelledProcessing, "Cancelled sending messages");
     }
 }
Пример #12
0
            string GetIdentity(IRoutingMessage routingMessage)
            {
                if (routingMessage.SystemProperties.TryGetValue(SystemProperties.ConnectionDeviceId, out string deviceId))
                {
                    return(routingMessage.SystemProperties.TryGetValue(SystemProperties.ConnectionModuleId, out string moduleId)
                        ? $"{deviceId}/{moduleId}"
                        : deviceId);
                }

                Events.DeviceIdNotFound(routingMessage);
                return(string.Empty);
            }
Пример #13
0
        public Task UpdateReportedPropertiesAsync(IIdentity identity, IMessage reportedPropertiesMessage)
        {
            Preconditions.CheckNotNull(identity, nameof(identity));
            Preconditions.CheckNotNull(reportedPropertiesMessage, nameof(reportedPropertiesMessage));
            Events.UpdateReportedPropertiesReceived(identity);
            Task cloudSendMessageTask = this.twinManager.UpdateReportedPropertiesAsync(identity.Id, reportedPropertiesMessage);

            IRoutingMessage routingMessage         = this.ProcessMessageInternal(reportedPropertiesMessage, false);
            Task            routingSendMessageTask = this.router.RouteAsync(routingMessage);

            return(Task.WhenAll(cloudSendMessageTask, routingSendMessageTask));
        }
Пример #14
0
 Util.Option <ICloudProxy> GetCloudProxy(IRoutingMessage routingMessage)
 {
     return(this.GetIdentity(routingMessage).Match(id =>
     {
         Util.Option <ICloudProxy> cloudProxy = this.cloudEndpoint.cloudProxyGetterFunc(id);
         if (!cloudProxy.HasValue)
         {
             Events.IoTHubNotConnected(id);
         }
         return cloudProxy;
     }, () => Option.None <ICloudProxy>()));
 }
Пример #15
0
 public Task ProcessDeviceMessage(IIdentity identity, IMessage message)
 {
     Preconditions.CheckNotNull(message, nameof(message));
     Preconditions.CheckNotNull(identity, nameof(identity));
     Events.MessageReceived(identity, message);
     MetricsV0.MessageCount(identity, 1);
     using (MetricsV0.MessageLatency(identity))
     {
         IRoutingMessage routingMessage = this.ProcessMessageInternal(message, true);
         Metrics.AddMessageSize(routingMessage.Size(), identity.Id);
         return(this.router.RouteAsync(routingMessage));
     }
 }
Пример #16
0
        IRoutingMessage ProcessMessageInternal(IMessage message, bool validateSize)
        {
            this.AddEdgeSystemProperties(message);
            IRoutingMessage routingMessage = this.messageConverter.FromMessage(Preconditions.CheckNotNull(message, nameof(message)));

            // Validate message size
            if (validateSize)
            {
                ValidateMessageSize(routingMessage);
            }

            return(routingMessage);
        }
Пример #17
0
        public Task ProcessDeviceMessage(IIdentity identity, IMessage message)
        {
            Preconditions.CheckNotNull(message, nameof(message));
            Preconditions.CheckNotNull(identity, nameof(identity));
            Events.MessageReceived(identity, message);

            IRoutingMessage routingMessage = this.ProcessMessageInternal(message, true);

            Metrics.AddMessageSize(routingMessage.Size(), identity.Id);
            Metrics.AddReceivedMessage(identity.Id, message.GetOutput());

            return(this.router.RouteAsync(routingMessage));
        }
Пример #18
0
 Task <Util.Option <ICloudProxy> > GetCloudProxy(IRoutingMessage routingMessage)
 {
     return(this.GetIdentity(routingMessage).Map(
                async id =>
     {
         Util.Option <ICloudProxy> cloudProxy = await this.cloudEndpoint.cloudProxyGetterFunc(id);
         if (!cloudProxy.HasValue)
         {
             Events.IoTHubNotConnected(id);
         }
         return cloudProxy;
     })
            .GetOrElse(() => Task.FromResult(Option.None <ICloudProxy>())));
 }
Пример #19
0
            internal static void RetryingMessage(IRoutingMessage message, Exception ex)
            {
                if (message.SystemProperties.TryGetValue(SystemProperties.ConnectionDeviceId, out string deviceId))
                {
                    string id = message.SystemProperties.TryGetValue(SystemProperties.ConnectionModuleId, out string moduleId)
                        ? $"{deviceId}/{moduleId}"
                        : deviceId;

                    // TODO - Add more info to this log message
                    Log.LogDebug((int)EventIds.RetryingMessages, Invariant($"Retrying sending message from {id} to Iot Hub due to exception {ex.GetType()}:{ex.Message}."));
                }
                else
                {
                    Log.LogDebug((int)EventIds.RetryingMessages, Invariant($"Retrying sending message to Iot Hub due to exception {ex.GetType()}:{ex.Message}."));
                }
            }
 Util.Option <ICloudProxy> GetCloudProxy(IRoutingMessage routingMessage)
 {
     if (routingMessage.SystemProperties.TryGetValue(SystemProperties.ConnectionDeviceId, out string deviceId))
     {
         string id = routingMessage.SystemProperties.TryGetValue(SystemProperties.ConnectionModuleId, out string moduleId)
             ? $"{deviceId}/{moduleId}"
             : deviceId;
         Util.Option <ICloudProxy> cloudProxy = this.cloudEndpoint.cloudProxyGetterFunc(id);
         if (!cloudProxy.HasValue)
         {
             Events.IoTHubNotConnected(id);
         }
         return(cloudProxy);
     }
     Events.DeviceIdNotFound(routingMessage);
     return(Option.None <ICloudProxy>());
 }
Пример #21
0
        public Task ProcessDeviceMessageBatch(IIdentity identity, IEnumerable <IMessage> messages)
        {
            IList <IMessage> messagesList = messages as IList <IMessage>
                                            ?? Preconditions.CheckNotNull(messages, nameof(messages)).ToList();

            Events.MessagesReceived(identity, messagesList);

            IEnumerable <IRoutingMessage> routingMessages = messagesList
                                                            .Select(
                m =>
            {
                IRoutingMessage routingMessage = this.ProcessMessageInternal(m, true);
                Metrics.AddMessageSize(routingMessage.Size(), identity.Id);
                return(routingMessage);
            });

            return(this.router.RouteAsync(routingMessages));
        }
Пример #22
0
            public async Task <ISinkResult> ProcessAsync(IRoutingMessage routingMessage, CancellationToken token)
            {
                Preconditions.CheckNotNull(routingMessage, nameof(routingMessage));

                if (token.IsCancellationRequested)
                {
                    Events.CancelledProcessingMessage(routingMessage);
                    var failed = new List <IRoutingMessage> {
                        routingMessage
                    };
                    var sendFailureDetails = new SendFailureDetails(FailureKind.Transient, new EdgeHubConnectionException($"Cancelled sending messages to IotHub for device {this.cloudEndpoint.Id}"));

                    return(new SinkResult <IRoutingMessage>(ImmutableList <IRoutingMessage> .Empty, failed, sendFailureDetails));
                }

                Util.Option <string> identity = this.GetIdentity(routingMessage);

                ISinkResult result = await identity.Match(
                    id => this.ProcessAsync(routingMessage, id),
                    () => this.ProcessNoIdentity(routingMessage));

                return(result);
            }
Пример #23
0
            ISinkResult HandleException(Exception ex, IRoutingMessage routingMessage)
            {
                if (IsRetryable(ex))
                {
                    var failed = new List <IRoutingMessage> {
                        routingMessage
                    };

                    Events.RetryingMessage(routingMessage, ex);
                    var sendFailureDetails = new SendFailureDetails(FailureKind.Transient, new EdgeHubIOException($"Error sending messages to IotHub for device {this.cloudEndpoint.Id}"));

                    return(new SinkResult <IRoutingMessage>(ImmutableList <IRoutingMessage> .Empty, failed, sendFailureDetails));
                }
                else
                {
                    Events.InvalidMessage(ex);
                    var invalid = new List <InvalidDetails <IRoutingMessage> > {
                        new InvalidDetails <IRoutingMessage>(routingMessage, FailureKind.InvalidInput)
                    };
                    var sendFailureDetails = new SendFailureDetails(FailureKind.InvalidInput, ex);

                    return(new SinkResult <IRoutingMessage>(ImmutableList <IRoutingMessage> .Empty, ImmutableList <IRoutingMessage> .Empty, invalid, sendFailureDetails));
                }
            }
Пример #24
0
 public static void CancelledProcessingMessage(IRoutingMessage message)
 {
     Log.LogDebug((int)EventIds.CancelledProcessing, $"Cancelled sending messages from offset {message.Offset}");
 }
Пример #25
0
 public Task <ISinkResult> ProcessAsync(IRoutingMessage routingMessage, CancellationToken token)
 {
     return(this.ProcessAsync(new[] { Preconditions.CheckNotNull(routingMessage, nameof(routingMessage)) }, token));
 }