public async Task StopListening()
        {
            try
            {
                // close any necesary receivers and the factory
                if (queueReceiver != null && queueReceiver.IsClosed == false)
                {
                    await queueReceiver.CloseAsync();
                }
                if (subscriptionReceiver != null && subscriptionReceiver.IsClosed == false)
                {
                    await subscriptionReceiver.CloseAsync();
                }
                await messagingFactory.CloseAsync();

                isListening = false;

                // remove the register from the store
                InMemoryTriggerStore.Instance.GetStore().Remove(workflowId);
                Trace.TraceInformation(String.Format("{0}: {1} Stopped listening, workflow id: {2}",
                                                     logMessageStub, DateTime.Now.ToString("yyyyMMdd HHmmss"), workflowId));
            }
            catch (Exception ex)
            {
                Trace.TraceError(String.Format("{0}: {1} Attempt to stop listening failed, workflow id: {2}, {3}{4}",
                                               logMessageStub, DateTime.Now.ToString("yyyyMMdd HHmmss"), workflowId, Environment.NewLine, ex.ToString()));
            }
        }
Beispiel #2
0
 public async Task Close()
 {
     if (_factory.IsClosed)
     {
         await _factory.CloseAsync();
     }
 }
        public async Task DisposeAsync(CancellationToken cancellationToken = new CancellationToken())
        {
            var address = _messagingFactory.Address.ToString();

            TransportLogMessages.DisconnectHost(address);

            await _messagingFactory.CloseAsync().ConfigureAwait(false);

            TransportLogMessages.DisconnectedHost(address);
        }
        public async Task DisposeAsync(CancellationToken cancellationToken = new CancellationToken())
        {
            if (_log.IsDebugEnabled)
            {
                _log.DebugFormat("Closing messaging factory: {0}", _messagingFactory.Address);
            }

            await _messagingFactory.CloseAsync().ConfigureAwait(false);

            if (_log.IsDebugEnabled)
            {
                _log.DebugFormat("Closed messaging factory: {0}", _messagingFactory.Address);
            }
        }
        public async Task CloseAsync(CancellationToken cancellationToken)
        {
            var tasks = new List <Task>();

            foreach (var r in mReceivers)
            {
                tasks.Add(r.StopAsync());
            }

            if (null != mMessagingFactory && !mMessagingFactory.IsClosed)
            {
                tasks.Add(mMessagingFactory.CloseAsync());
            }

            await Task.WhenAll(tasks);

            mReceivers.ForEach(r => r = null);
            mReceivers.Clear();
        }
            async Task HostHandle.Stop(CancellationToken cancellationToken)
            {
                try
                {
                    MessagingFactory factory = await _messagingFactoryTask.ConfigureAwait(false);

                    if (!factory.IsClosed)
                    {
                        await factory.CloseAsync().ConfigureAwait(false);
                    }
                }
                catch (Exception ex)
                {
                    if (_log.IsWarnEnabled)
                    {
                        _log.Warn("Exception closing messaging factory", ex);
                    }
                }
            }
Beispiel #7
0
        public async Task DisposeAsync(CancellationToken cancellationToken = new CancellationToken())
        {
            await _messagingFactory.CloseAsync().ConfigureAwait(false);

            LogContext.Debug?.Log("Closed messaging factory: {Host}", _messagingFactory.Address);
        }
        /// <summary>
        /// This is the main entry point for your service replica.
        /// This method executes when this replica of your service becomes primary and has write status.
        /// </summary>
        /// <param name="cancellationToken">Canceled when Service Fabric needs to shut down this service replica.</param>
        protected override async Task RunAsync(CancellationToken cancellationToken)
        {
            // Get the IoT Hub connection string from the Settings.xml config file
            // from a configuration package named "Config"
            string iotHubConnectionString =
                this.Context.CodePackageActivationContext
                .GetConfigurationPackageObject("Config")
                .Settings
                .Sections["IoTHubConfigInformation"]
                .Parameters["ConnectionString"]
                .Value;
            string iotHubProcessOnlyFutureEvents =
                this.Context.CodePackageActivationContext
                .GetConfigurationPackageObject("Config")
                .Settings
                .Sections["IoTHubConfigInformation"]
                .Parameters["ProcessOnlyFutureEvents"]
                .Value.ToLower();

            ServiceEventSource.Current.ServiceMessage(this.Context, $"RouterService - {ServiceUniqueId} - RunAsync - Starting service  - Process Only Future Events[{iotHubProcessOnlyFutureEvents}] - IoTHub Connection String[{iotHubConnectionString}]");

            // These Reliable Dictionaries are used to keep track of our position in IoT Hub.
            // If this service fails over, this will allow it to pick up where it left off in the event stream.
            IReliableDictionary <string, string> offsetDictionary =
                await this.StateManager.GetOrAddAsync <IReliableDictionary <string, string> >(OffsetDictionaryName);

            IReliableDictionary <string, long> epochDictionary =
                await this.StateManager.GetOrAddAsync <IReliableDictionary <string, long> >(EpochDictionaryName);

            // Each partition of this service corresponds to a partition in IoT Hub.
            // IoT Hub partitions are numbered 0..n-1, up to n = 32.
            // This service needs to use an identical partitioning scheme.
            // The low key of every partition corresponds to an IoT Hub partition.
            Int64RangePartitionInformation partitionInfo = (Int64RangePartitionInformation)this.Partition.PartitionInfo;
            long servicePartitionKey = partitionInfo.LowKey;

            EventHubReceiver eventHubReceiver = null;
            MessagingFactory messagingFactory = null;

            try
            {
                // HttpClient is designed as a shared object.
                // A single instance should be used throughout the lifetime of RunAsync.
                using (HttpClient httpClient = new HttpClient(new HttpServiceClientHandler()))
                {
                    int  offsetIteration = 0;
                    bool IsConnected     = false;

                    while (true)
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        if (!IsConnected)
                        {
                            // Get an EventHubReceiver and the MessagingFactory used to create it.
                            // The EventHubReceiver is used to get events from IoT Hub.
                            // The MessagingFactory is just saved for later so it can be closed before RunAsync exits.
                            Tuple <EventHubReceiver, MessagingFactory> iotHubInfo = await this.ConnectToIoTHubAsync(iotHubConnectionString, servicePartitionKey, epochDictionary, offsetDictionary, iotHubProcessOnlyFutureEvents);

                            eventHubReceiver = iotHubInfo.Item1;
                            messagingFactory = iotHubInfo.Item2;

                            IsConnected = true;
                        }

                        Uri postUrl = null;

                        try
                        {
                            // It's important to set a low wait time here in lieu of a cancellation token
                            // so that this doesn't block RunAsync from exiting when Service Fabric needs it to complete.
                            // ReceiveAsync is a long-poll operation, so the timeout should not be too low,
                            // yet not too high to block RunAsync from exiting within a few seconds.
                            using (EventData eventData = await eventHubReceiver.ReceiveAsync(TimeSpan.FromSeconds(5)))
                            {
                                if (eventData == null)
                                {
                                    ServiceEventSource.Current.ServiceMessage(this.Context, $"RouterService - {ServiceUniqueId} - RunAsync - No event data available on hub '{eventHubReceiver.Name}'");
                                    await Task.Delay(global::Iot.Common.Names.IoTHubRetryWaitIntervalsInMills);

                                    continue;
                                }
                                else
                                {
                                    ServiceEventSource.Current.ServiceMessage(this.Context, $"RouterService - {ServiceUniqueId} - RunAsync - Received event data from hub '{eventHubReceiver.Name}' - Enqueued Time[{eventData.EnqueuedTimeUtc}] - Partition '{eventData.PartitionKey}' Sequence # '{eventData.SequenceNumber}'");
                                }

                                string targetSite = (string)eventData.Properties[global::Iot.Common.Names.EventKeyFieldTargetSite];
                                string deviceId   = (string)eventData.Properties[global::Iot.Common.Names.EventKeyFieldDeviceId];

                                // This is the named service instance of the target site data service that the event should be sent to.
                                // The targetSite id is part of the named service instance name.
                                // The incoming device data stream specifie which target site the data belongs to.
                                string prefix                        = global::Iot.Common.Names.InsightApplicationNamePrefix;
                                string serviceName                   = global::Iot.Common.Names.InsightDataServiceName;
                                Uri    targetSiteServiceName         = new Uri($"{prefix}/{targetSite}/{serviceName}");
                                long   targetSiteServicePartitionKey = FnvHash.Hash(deviceId);

                                ServiceEventSource.Current.ServiceMessage(this.Context, $"RouterService - {ServiceUniqueId} - RunAsync - About to post data to Insight Data Service from device '{deviceId}' to target site '{targetSite}' - partitionKey '{targetSiteServicePartitionKey}' - Target Service Name '{targetSiteServiceName}'");

                                // The target site data service exposes an HTTP API.
                                // For incoming device events, the URL is /api/events/{deviceId}
                                // This sets up a URL and sends a POST request with the device JSON payload.
                                postUrl = new HttpServiceUriBuilder()
                                          .SetServiceName(targetSiteServiceName)
                                          .SetPartitionKey(targetSiteServicePartitionKey)
                                          .SetServicePathAndQuery($"/api/events/{deviceId}")
                                          .Build();

                                ServiceEventSource.Current.ServiceMessage(this.Context, $"RouterService - {ServiceUniqueId} - RunAsync - Ready to post data to Insight Data Service from device '{deviceId}' to taget site '{targetSite}' - partitionKey '{targetSiteServicePartitionKey}' - Target Service Name '{targetSiteServiceName}' - url '{postUrl.PathAndQuery}'");

                                // The device stream payload isn't deserialized and buffered in memory here.
                                // Instead, we just can just hook the incoming stream from Iot Hub right into the HTTP request stream.
                                using (Stream eventStream = eventData.GetBodyStream())
                                {
                                    using (StreamContent postContent = new StreamContent(eventStream))
                                    {
                                        postContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");

                                        HttpResponseMessage response = await httpClient.PostAsync(postUrl, postContent, cancellationToken);

                                        if (response.StatusCode == System.Net.HttpStatusCode.BadRequest)
                                        {
                                            // This service expects the receiving target site service to return HTTP 400 if the device message was malformed.
                                            // In this example, the message is simply logged.
                                            // Your application should handle all possible error status codes from the receiving service
                                            // and treat the message as a "poison" message.
                                            // Message processing should be allowed to continue after a poison message is detected.

                                            string responseContent = await response.Content.ReadAsStringAsync();

                                            ServiceEventSource.Current.ServiceMessage(
                                                this.Context,
                                                $"RouterService - {ServiceUniqueId} - RunAsync - Insight service '{targetSiteServiceName}' returned HTTP 400 due to a bad device message from device '{deviceId}'. Error message: '{responseContent}'");
                                        }

                                        ServiceEventSource.Current.ServiceMessage(
                                            this.Context,
                                            $"RouterService - {ServiceUniqueId} - RunAsync - Sent event data to Insight service '{targetSiteServiceName}' with partition key '{targetSiteServicePartitionKey}'. Result: {response.StatusCode.ToString()}");
                                    }
                                }

                                // Save the current Iot Hub data stream offset.
                                // This will allow the service to pick up from its current location if it fails over.
                                // Duplicate device messages may still be sent to the the target site service
                                // if this service fails over after the message is sent but before the offset is saved.
                                if (++offsetIteration % OffsetInterval == 0)
                                {
                                    ServiceEventSource.Current.ServiceMessage(
                                        this.Context,
                                        $"RouterService - {ServiceUniqueId} - RunAsync - Saving offset {eventData.Offset}");

                                    using (ITransaction tx = this.StateManager.CreateTransaction())
                                    {
                                        await offsetDictionary.SetAsync(tx, "offset", eventData.Offset);

                                        await tx.CommitAsync();
                                    }

                                    offsetIteration = 0;
                                }
                            }
                        }
                        catch (Microsoft.ServiceBus.Messaging.ReceiverDisconnectedException rde)
                        {
                            // transient error. Retry.
                            ServiceEventSource.Current.ServiceMessage(this.Context, $"RouterService - {ServiceUniqueId} - RunAsync - Receiver Disconnected Exception in RunAsync: {rde.ToString()}");

                            IsConnected = false;
                        }
                        catch (TimeoutException te)
                        {
                            // transient error. Retry.
                            ServiceEventSource.Current.ServiceMessage(this.Context, $"RouterService - {ServiceUniqueId} - RunAsync - TimeoutException in RunAsync: {te.ToString()}");
                        }
                        catch (FabricTransientException fte)
                        {
                            // transient error. Retry.
                            ServiceEventSource.Current.ServiceMessage(this.Context, $"RouterService - {ServiceUniqueId} - RunAsync - FabricTransientException in RunAsync: {fte.ToString()}");
                        }
                        catch (FabricNotPrimaryException fnpe)
                        {
                            ServiceEventSource.Current.ServiceMessage(this.Context, $"RouterService - {ServiceUniqueId} - RunAsync - FabricNotPrimaryException Exception - Message=[{fnpe}]");

                            // not primary any more, time to quit.
                            return;
                        }
                        catch (Exception ex)
                        {
                            IsConnected = false;
                            string url = postUrl == null ? "Url undefined" : postUrl.ToString();
                            //ServiceEventSource.Current.ServiceMessage(this.Context, $"RouterService - {ServiceUniqueId} - RunAsync - General Exception Url=[{url}]- Message=[{ex}] - Inner Exception=[{ex.InnerException.Message ?? "ex.InnerException is null"}] Call Stack=[{ex.StackTrace ?? "ex.StackTrace is null"}] - Stack trace of inner exception=[{ex.InnerException.StackTrace ?? "ex.InnerException.StackTrace is null"}]");

                            ServiceEventSource.Current.ServiceMessage(this.Context, $"RouterService - {ServiceUniqueId} - RunAsync - General Exception Message[{ex.Message}] for url[{url}]");
                        }
                    }
                }
            }
            finally
            {
                if (messagingFactory != null)
                {
                    await messagingFactory.CloseAsync();
                }
            }
        }
 public async Task CloseAsync()
 {
     await _factory.CloseAsync();
 }
        /// <summary>
        /// This is the main entry point for your service replica.
        /// This method executes when this replica of your service becomes primary and has write status.
        /// </summary>
        /// <param name="cancellationToken">Canceled when Service Fabric needs to shut down this service replica.</param>
        protected override async Task RunAsync(CancellationToken cancellationToken)
        {
            // Get the IoT Hub connection string from the Settings.xml config file
            // from a configuration package named "Config"
            string iotHubConnectionString =
                this.Context.CodePackageActivationContext
                .GetConfigurationPackageObject("Config")
                .Settings
                .Sections["IoTHubConfigInformation"]
                .Parameters["ConnectionString"]
                .Value;

            // These Reliable Dictionaries are used to keep track of our position in IoT Hub.
            // If this service fails over, this will allow it to pick up where it left off in the event stream.
            IReliableDictionary <string, string> offsetDictionary =
                await this.StateManager.GetOrAddAsync <IReliableDictionary <string, string> >(OffsetDictionaryName);

            IReliableDictionary <string, long> epochDictionary =
                await this.StateManager.GetOrAddAsync <IReliableDictionary <string, long> >(EpochDictionaryName);

            // Each partition of this service corresponds to a partition in IoT Hub.
            // IoT Hub partitions are numbered 0..n-1, up to n = 32.
            // This service needs to use an identical partitioning scheme.
            // The low key of every partition corresponds to an IoT Hub partition.
            Int64RangePartitionInformation partitionInfo = (Int64RangePartitionInformation)this.Partition.PartitionInfo;
            long servicePartitionKey = partitionInfo.LowKey;

            EventHubReceiver eventHubReceiver = null;
            MessagingFactory messagingFactory = null;

            try
            {
                // Get an EventHubReceiver and the MessagingFactory used to create it.
                // The EventHubReceiver is used to get events from IoT Hub.
                // The MessagingFactory is just saved for later so it can be closed before RunAsync exits.
                Tuple <EventHubReceiver, MessagingFactory> iotHubInfo =
                    await this.ConnectToIoTHubAsync(iotHubConnectionString, servicePartitionKey, epochDictionary, offsetDictionary);

                eventHubReceiver = iotHubInfo.Item1;
                messagingFactory = iotHubInfo.Item2;

                // HttpClient is designed as a shared object.
                // A single instance should be used throughout the lifetime of RunAsync.
                using (HttpClient httpClient = new HttpClient(new HttpServiceClientHandler()))
                {
                    int offsetIteration = 0;

                    while (true)
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        try
                        {
                            // It's important to set a low wait time here in lieu of a cancellation token
                            // so that this doesn't block RunAsync from exiting when Service Fabric needs it to complete.
                            // ReceiveAsync is a long-poll operation, so the timeout should not be too low,
                            // yet not too high to block RunAsync from exiting within a few seconds.
                            using (EventData eventData = await eventHubReceiver.ReceiveAsync(TimeSpan.FromSeconds(5)))
                            {
                                if (eventData == null)
                                {
                                    continue;
                                }

                                string tenantId = (string)eventData.Properties["TenantID"];
                                string deviceId = (string)eventData.Properties["DeviceID"];

                                // This is the named service instance of the tenant data service that the event should be sent to.
                                // The tenant ID is part of the named service instance name.
                                // The incoming device data stream specifie which tenant the data belongs to.
                                Uri  tenantServiceName         = new Uri($"{Names.InsightApplicationNamePrefix}/{tenantId}/{Names.InsightDataServiceName}");
                                long tenantServicePartitionKey = FnvHash.Hash(deviceId);

                                // The tenant data service exposes an HTTP API.
                                // For incoming device events, the URL is /api/events/{deviceId}
                                // This sets up a URL and sends a POST request with the device JSON payload.
                                Uri postUrl = new HttpServiceUriBuilder()
                                              .SetServiceName(tenantServiceName)
                                              .SetPartitionKey(tenantServicePartitionKey)
                                              .SetServicePathAndQuery($"/api/events/{deviceId}")
                                              .Build();

                                // The device stream payload isn't deserialized and buffered in memory here.
                                // Instead, we just can just hook the incoming stream from Iot Hub right into the HTTP request stream.
                                using (Stream eventStream = eventData.GetBodyStream())
                                {
                                    using (StreamContent postContent = new StreamContent(eventStream))
                                    {
                                        postContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");

                                        HttpResponseMessage response = await httpClient.PostAsync(postUrl, postContent, cancellationToken);

                                        ServiceEventSource.Current.ServiceMessage(
                                            this.Context,
                                            "Sent event data to insight service '{0}' with partition key '{1}'. Result: {2}",
                                            tenantServiceName,
                                            tenantServicePartitionKey,
                                            response.StatusCode.ToString());

                                        if (response.StatusCode == System.Net.HttpStatusCode.BadRequest)
                                        {
                                            // This service expects the receiving tenant service to return HTTP 400 if the device message was malformed.
                                            // In this example, the message is simply logged.
                                            // Your application should handle all possible error status codes from the receiving service
                                            // and treat the message as a "poison" message.
                                            // Message processing should be allowed to continue after a poison message is detected.

                                            string responseContent = await response.Content.ReadAsStringAsync();

                                            ServiceEventSource.Current.ServiceMessage(
                                                this.Context,
                                                "Insight service '{0}' returned HTTP 400 due to a bad device message from device '{1}'. Error message: '{2}'",
                                                tenantServiceName,
                                                deviceId,
                                                responseContent);
                                        }
                                    }
                                }

                                // Save the current Iot Hub data stream offset.
                                // This will allow the service to pick up from its current location if it fails over.
                                // Duplicate device messages may still be sent to the the tenant service
                                // if this service fails over after the message is sent but before the offset is saved.
                                if (++offsetIteration % OffsetInterval == 0)
                                {
                                    ServiceEventSource.Current.ServiceMessage(
                                        this.Context,
                                        "Saving offset {0}",
                                        eventData.Offset);

                                    using (ITransaction tx = this.StateManager.CreateTransaction())
                                    {
                                        await offsetDictionary.SetAsync(tx, "offset", eventData.Offset);

                                        await tx.CommitAsync();
                                    }

                                    offsetIteration = 0;
                                }
                            }
                        }
                        catch (TimeoutException te)
                        {
                            // transient error. Retry.
                            ServiceEventSource.Current.ServiceMessage(this.Context, $"TimeoutException in RunAsync: {te.ToString()}");
                        }
                        catch (FabricTransientException fte)
                        {
                            // transient error. Retry.
                            ServiceEventSource.Current.ServiceMessage(this.Context, $"FabricTransientException in RunAsync: {fte.ToString()}");
                        }
                        catch (FabricNotPrimaryException)
                        {
                            // not primary any more, time to quit.
                            return;
                        }
                        catch (Exception ex)
                        {
                            ServiceEventSource.Current.ServiceMessage(this.Context, ex.ToString());

                            throw;
                        }
                    }
                }
            }
            finally
            {
                if (messagingFactory != null)
                {
                    await messagingFactory.CloseAsync();
                }
            }
        }
Beispiel #11
0
        /// <summary>
        /// This is the main entry point for your service replica.
        /// This method executes when this replica of your service becomes primary and has write status.
        /// </summary>
        /// <param name="cancellationToken">Canceled when Service Fabric needs to shut down this service replica.</param>
        protected override async Task RunAsync(CancellationToken cancellationToken)
        {
            string iotHubConnectionstring = "HostName=iotdemogittehub.azure-devices.net;SharedAccessKeyName=service;SharedAccessKey=IGHntc2VC4+pthyOyyRf9jy6kTU11n+WgVMJ9N7VWUw=";

            // These Reliable Dictionaries are used to keep track of our position in IoT Hub.
            // If this service fails over, this will allow it to pick up where it left off in the event stream.
            var offsetDictionary = await StateManager.GetOrAddAsync <IReliableDictionary <string, string> >(OffsetDictionaryName);

            var epochDictionary = await this.StateManager.GetOrAddAsync <IReliableDictionary <string, long> >(EpochDictionaryName);

            // Each partition of this service corresponds to a partition in IoT Hub.
            // IoT Hub partitions are numbered 0..n-1, up to n = 32.
            // This service needs to use an identical partitioning scheme.
            // The low key of every partition corresponds to an IoT Hub partition.
            var  partitionInfo       = (Int64RangePartitionInformation)Partition.PartitionInfo;
            long servicePartitionKey = partitionInfo.LowKey;

            EventHubReceiver eventHubReceiver = null;
            MessagingFactory messagingFactory = null;

            try
            {
                // Get an EventHubReceiver and the MessagingFactory used to create it.
                // The EventHubReceiver is used to get events from IoT Hub.
                // The MessagingFactory is just saved for later so it can be closed before RunAsync exits.
                var iotHubInfo = await ConnectToIoTHubAsync(iotHubConnectionstring, servicePartitionKey, epochDictionary, offsetDictionary);

                eventHubReceiver = iotHubInfo.Item1;
                messagingFactory = iotHubInfo.Item2;

                if (eventHubReceiver == null || messagingFactory == null)
                {
                    return;
                }

                int offsetIteration = 0;

                while (true)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    try
                    {
                        // It's important to set a low wait time here in lieu of a cancellation token
                        // so that this doesn't block RunAsync from exiting when Service Fabric needs it to complete.
                        // ReceiveAsync is a long-poll operation, so the timeout should not be too low,
                        // yet not too high to block RunAsync from exiting within a few seconds.
                        using (EventData eventData = await eventHubReceiver.ReceiveAsync(TimeSpan.FromSeconds(5)))
                        {
                            if (eventData == null)
                            {
                                continue;
                            }

                            string deviceId = (string)eventData.Properties["DeviceID"];

                            var deviceactorProxy = ActorProxy.Create <IIoTDeviceActor>(new ActorId(deviceId), new Uri("fabric:/IotDemoApp/IoTDeviceActorService"));
                            //await deviceactorProxy.SendDeviceMessage((string)eventData.Properties["Temparature"], cancellationToken);
                            await deviceactorProxy.SendDeviceMessageProps(eventData.Properties, cancellationToken);

                            ServiceEventSource.Current.ServiceMessage(
                                Context,
                                "Sent event data to actor service '{0}'.",
                                deviceId);

                            if (++offsetIteration % OffsetInterval == 0)
                            {
                                ServiceEventSource.Current.ServiceMessage(
                                    Context,
                                    "Saving offset {0}",
                                    eventData.Offset);

                                using (ITransaction tx = StateManager.CreateTransaction())
                                {
                                    await offsetDictionary.SetAsync(tx, "offset", eventData.Offset);

                                    await tx.CommitAsync();
                                }

                                offsetIteration = 0;
                            }
                        }
                    }
                    catch (TimeoutException te)
                    {
                        // transient error. Retry.
                        ServiceEventSource.Current.ServiceMessage(Context, $"TimeoutException in RunAsync: {te.ToString()}");
                    }
                    catch (FabricTransientException fte)
                    {
                        // transient error. Retry.
                        ServiceEventSource.Current.ServiceMessage(Context, $"FabricTransientException in RunAsync: {fte.ToString()}");
                    }
                    catch (FabricNotPrimaryException)
                    {
                        // not primary any more, time to quit.
                        return;
                    }
                    catch (Exception ex)
                    {
                        ServiceEventSource.Current.ServiceMessage(Context, ex.ToString());

                        throw;
                    }
                }
            }
            finally
            {
                if (messagingFactory != null)
                {
                    await messagingFactory.CloseAsync();
                }
            }
        }
        /// <summary>
        /// This is the main entry point for your service replica.
        /// This method executes when this replica of your service becomes primary and has write status.
        /// </summary>
        /// <param name="cancellationToken">Canceled when Service Fabric needs to shut down this service replica.</param>
        protected override async Task RunAsync(CancellationToken cancellationToken)
        {
            // These Reliable Dictionaries are used to keep track of our position in IoT Hub.
            // If this service fails over, this will allow it to pick up where it left off in the event stream.
            IReliableDictionary <string, string> offsetDictionary =
                await this.StateManager.GetOrAddAsync <IReliableDictionary <string, string> >(OffsetDictionaryName);

            IReliableDictionary <string, long> epochDictionary =
                await this.StateManager.GetOrAddAsync <IReliableDictionary <string, long> >(EpochDictionaryName);


            // Each partition of this service corresponds to a partition in IoT Hub.
            // IoT Hub partitions are numbered 0..n-1, up to n = 32.
            // This service needs to use an identical partitioning scheme.
            // The low key of every partition corresponds to an IoT Hub partition.
            Int64RangePartitionInformation partitionInfo = (Int64RangePartitionInformation)this.Partition.PartitionInfo;
            long servicePartitionKey = partitionInfo.LowKey;

            EventHubReceiver eventHubReceiver = null;
            MessagingFactory messagingFactory = null;


            try
            {
                int offsetIteration = 0;
                // Get an EventHubReceiver and the MessagingFactory used to create it.
                // The EventHubReceiver is used to get events from IoT Hub.
                // The MessagingFactory is just saved for later so it can be closed before RunAsync exits.

                Tuple <EventHubReceiver, MessagingFactory> iotHubInfo =
                    await this.ConnectToIoTHubAsync(iotHubConnectionString, servicePartitionKey, epochDictionary, offsetDictionary);

                eventHubReceiver = iotHubInfo.Item1;
                messagingFactory = iotHubInfo.Item2;
                while (true)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    try
                    {
                        // It's important to set a low wait time here in lieu of a cancellation token
                        // so that this doesn't block RunAsync from exiting when Service Fabric needs it to complete.
                        // ReceiveAsync is a long-poll operation, so the timeout should not be too low,
                        // yet not too high to block RunAsync from exiting within a few seconds.
                        using (EventData eventData = await eventHubReceiver.ReceiveAsync(TimeSpan.FromSeconds(5)))
                        {
                            if (eventData == null)
                            {
                                continue;
                            }
                            //Do something with eventData
                            // Save the current Iot Hub data stream offset.
                            // This will allow the service to pick up from its current location if it fails over.
                            // Duplicate device messages may still be sent to the the tenant service
                            // if this service fails over after the message is sent but before the offset is saved.
                            if (++offsetIteration % OffsetInterval == 0)
                            {
                                ServiceEventSource.Current.ServiceMessage(
                                    this.Context,
                                    $"{servicePartitionKey} - Saving offset {eventData.Offset}"
                                    );

                                using (ITransaction tx = this.StateManager.CreateTransaction())
                                {
                                    await offsetDictionary.SetAsync(tx, "offset", eventData.Offset);

                                    await tx.CommitAsync();
                                }

                                offsetIteration = 0;
                            }
                        }
                    }
                    catch (TimeoutException te)
                    {
                        // transient error. Retry.
                        ServiceEventSource.Current.ServiceMessage(this.Context, $"TimeoutException in RunAsync: {te.ToString()}");
                    }
                    catch (FabricTransientException fte)
                    {
                        // transient error. Retry.
                        ServiceEventSource.Current.ServiceMessage(this.Context, $"FabricTransientException in RunAsync: {fte.ToString()}");
                    }
                    catch (FabricNotPrimaryException)
                    {
                        // not primary any more, time to quit.
                        return;
                    }
                    catch (Exception ex)
                    {
                        ServiceEventSource.Current.ServiceMessage(this.Context, ex.ToString());

                        throw;
                    }
                }
            }
            finally
            {
                if (messagingFactory != null)
                {
                    await messagingFactory.CloseAsync();
                }
            }
        }
Beispiel #13
0
 public Task CloseAsync()
 {
     return(factory.CloseAsync());
 }