public async Task Receive() { try { using (ITransaction tx = stateManager.CreateTransaction()) { ConditionalValue <string> offsetResult = await offsetDictionary.TryGetValueAsync(tx, "offset", LockMode.Default); ConditionalValue <long> epochResult = await epochDictionary.TryGetValueAsync(tx, "epoch", LockMode.Update); long newEpoch = epochResult.HasValue ? epochResult.Value + 1 : 0; await epochDictionary.SetAsync(tx, "epoch", newEpoch); PartitionReceiver partitionReceiver; if (offsetResult.HasValue) { partitionReceiver = eventHubClient.CreateEpochReceiver(PartitionReceiver.DefaultConsumerGroupName, "3", //Convert.ToString(this.servicePartitionKey), offsetResult.Value, newEpoch); } else { partitionReceiver = eventHubClient.CreateEpochReceiver(PartitionReceiver.DefaultConsumerGroupName, Convert.ToString(this.servicePartitionKey), "-1", newEpoch); } ServiceEventSource.Current.ServiceMessage(this.serviceContext, $"Partition Id: {servicePartitionKey}; offset: {offsetResult.Value}; Epoch: {newEpoch}"); var ehEvents = await partitionReceiver.ReceiveAsync(1); await GenerateActors(ehEvents, tx); await tx.CommitAsync(); } } catch (EventHubsException ex) { ServiceEventSource.Current.ServiceMessage(this.serviceContext, ex.Message); } catch (Exception ex) { ServiceEventSource.Current.ServiceMessage(this.serviceContext, ex.Message); } }
/// <summary> /// Creates an PartitionReceiver from the given connection sting and partition key. /// The Reliable Dictionaries are used to create a receiver from wherever the service last left off, /// or from the current date/time if it's the first time the service is coming up. /// </summary> /// <param name="client"></param> /// <param name="consumerGroup"></param> /// <param name="servicePartitionKey"></param> /// <param name="epochDictionary"></param> /// <param name="offsetDictionary"></param> /// <returns>PartitionReceiver</returns> private async Task <PartitionReceiver> ConnectToIoTHubAsync( EventHubClient client, string consumerGroup, long servicePartitionKey, IReliableDictionary <string, long> epochDictionary, IReliableDictionary <string, string> offsetDictionary) { // This gives each partition its own dedicated TCP connection to IoT Hub. var eventHubRuntimeInfo = await client.GetRuntimeInformationAsync(); PartitionReceiver partitionReceiver; // Get an IoT Hub partition ID that corresponds to this partition's low key. // This assumes that this service has a partition count 'n' that is equal to the IoT Hub partition count and a partition range of 0..n-1. // For example, given an IoT Hub with 32 partitions, this service should be created with: // partition count = 32 // partition range = 0..31 string eventHubPartitionId = eventHubRuntimeInfo.PartitionIds[servicePartitionKey]; using (var tx = this.StateManager.CreateTransaction()) { ConditionalValue <string> offsetResult = await offsetDictionary.TryGetValueAsync(tx, "offset", LockMode.Default); ConditionalValue <long> epochResult = await epochDictionary.TryGetValueAsync(tx, "epoch", LockMode.Update); long newEpoch = epochResult.HasValue ? epochResult.Value + 1 : 0; if (offsetResult.HasValue) { // continue where the service left off before the last failover or restart. ServiceEventSource.Current.ServiceMessage( this.Context, "Creating EventHub listener on partition {0} with offset {1}", eventHubPartitionId, offsetResult.Value); partitionReceiver = client.CreateEpochReceiver(consumerGroup, eventHubPartitionId, EventPosition.FromOffset(offsetResult.Value), newEpoch); } else { // first time this service is running so there is no offset value yet. // start with the current time. ServiceEventSource.Current.ServiceMessage( this.Context, "Creating EventHub listener on partition {0} with offset {1}", eventHubPartitionId, DateTime.UtcNow); partitionReceiver = client.CreateEpochReceiver(consumerGroup, eventHubPartitionId, EventPosition.FromEnqueuedTime(DateTime.UtcNow), newEpoch); } // epoch is recorded each time the service fails over or restarts. await epochDictionary.SetAsync(tx, "epoch", newEpoch); await tx.CommitAsync(); } return(partitionReceiver); }