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>()))); }
async Task <ISinkResult <IRoutingMessage> > ProcessClientMessagesBatch(string id, List <IRoutingMessage> routingMessages, CancellationToken token) { if (string.IsNullOrEmpty(id)) { return(HandleNoIdentity(routingMessages)); } if (token.IsCancellationRequested) { return(HandleCancelled(routingMessages)); } Util.Option <ICloudProxy> cloudProxy = await this.cloudEndpoint.cloudProxyGetterFunc(id); ISinkResult result = await cloudProxy.Match( async cp => { try { List <IMessage> messages = routingMessages .Select(r => this.cloudEndpoint.messageConverter.ToMessage(r)) .ToList(); using (MetricsV0.CloudLatency(id)) { if (messages.Count == 1) { await cp.SendMessageAsync(messages[0]); } else { await cp.SendMessageBatchAsync(messages); } } MetricsV0.MessageCount(id, messages.Count); return(new SinkResult <IRoutingMessage>(routingMessages)); } catch (Exception ex) { return(this.HandleException(ex, id, routingMessages)); } }, () => Task.FromResult(HandleNoConnection(id, routingMessages))); return(result); }
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 = 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 { await cp.SendMessageAsync(message); succeeded.Add(routingMessage); } 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 <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>()); }
Util.Option <IDeviceProxy> GetDeviceProxy() { this.devicePoxy = this.devicePoxy.Filter(d => d.IsActive) .Map(d => Option.Some(d)) .GetOrElse( () => { Util.Option <IDeviceProxy> currentDeviceProxy = this.moduleEndpoint.connectionManager.GetDeviceConnection(this.moduleEndpoint.moduleId).Filter(d => d.IsActive); if (currentDeviceProxy.HasValue) { if (this.moduleEndpoint.connectionManager.GetSubscriptions(this.moduleEndpoint.moduleId) .Filter(s => s.TryGetValue(DeviceSubscription.ModuleMessages, out bool isActive) && isActive) .HasValue) { return(currentDeviceProxy); } else { Events.NoMessagesSubscription(this.moduleEndpoint.moduleId); } }
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); }
RetrieveNextBatch() { Seq < Util.Try <ReplayCompletion> > msg; using (var conn = _connectionFactory.GetConnection()) { var waited = Messages(conn, persistenceId, opt.Item1, toSequenceNr, batchSize); msg = await waited .RunWith( ExtSeq.Seq <Util.Try <ReplayCompletion> >(), mat); } var hasMoreEvents = msg.Count == batchSize; var lastMsg = msg.LastOrDefault(); Util.Option <long> lastSeq = Util.Option <long> .None; if (lastMsg != null && lastMsg.IsSuccess) { lastSeq = lastMsg.Success.Select(r => r.repr.SequenceNr); } else if (lastMsg != null && lastMsg.Failure.HasValue) { throw lastMsg.Failure.Value; } var hasLastEvent = lastSeq.HasValue && lastSeq.Value >= toSequenceNr; FlowControl nextControl = null; if (hasLastEvent || opt.Item1 > toSequenceNr) { nextControl = FlowControl.Stop.Instance; } else if (hasMoreEvents) { nextControl = FlowControl.Continue.Instance; } else if (refreshInterval.HasValue == false) { nextControl = FlowControl.Stop.Instance; } else { nextControl = FlowControl.ContinueDelayed .Instance; } long nextFrom = 0; if (lastSeq.HasValue) { nextFrom = lastSeq.Value + 1; } else { nextFrom = opt.Item1; } return(new Util.Option <((long, FlowControl), Seq <Util.Try <ReplayCompletion> >)>(( (nextFrom, nextControl), msg))); }