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); }
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); }
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}"); } }
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)); }
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"); } }
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))); }
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))); }
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)); }
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>()); }
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); }
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"); } }
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); }
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)); }
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>())); }
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)); } }
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); }
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)); }
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>()))); }
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>()); }
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)); }
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); }
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)); } }
public static void CancelledProcessingMessage(IRoutingMessage message) { Log.LogDebug((int)EventIds.CancelledProcessing, $"Cancelled sending messages from offset {message.Offset}"); }
public Task <ISinkResult> ProcessAsync(IRoutingMessage routingMessage, CancellationToken token) { return(this.ProcessAsync(new[] { Preconditions.CheckNotNull(routingMessage, nameof(routingMessage)) }, token)); }