public async Task ClaimOwnershipAsyncReturnsOnlyTheSuccessfullyClaimedOwnership() { var partitionManager = new InMemoryPartitionManager(); var ownershipList = new List <PartitionOwnership>(); var ownershipCount = 5; for (int i = 0; i < ownershipCount; i++) { ownershipList.Add( new PartitionOwnership ( "namespace", "eventHubName", "consumerGroup", "ownerIdentifier", $"partitionId { i }" )); } await partitionManager.ClaimOwnershipAsync(ownershipList); // The ETags must have been set by the partition manager. var eTags = ownershipList.Select(ownership => ownership.ETag).ToList(); ownershipList.Clear(); // Use a valid eTag when 'i' is odd. This way, we can expect 'ownershipCount / 2' successful // claims (rounded down). var expectedClaimedCount = ownershipCount / 2; for (int i = 0; i < ownershipCount; i++) { ownershipList.Add( new PartitionOwnership ( "namespace", "eventHubName", "consumerGroup", "ownerIdentifier", $"partitionId { i }", offset: i, eTag: i % 2 == 1 ? eTags[i] : null )); } IEnumerable <PartitionOwnership> claimedOwnership = await partitionManager.ClaimOwnershipAsync(ownershipList); Assert.That(claimedOwnership, Is.Not.Null); Assert.That(claimedOwnership.Count, Is.EqualTo(expectedClaimedCount)); Assert.That(claimedOwnership.OrderBy(ownership => ownership.Offset).SequenceEqual(ownershipList.Where(ownership => ownership.Offset % 2 == 1)), Is.True); }
public async Task OwnershipClaimDoesNotInterfereWithOtherNamespaces() { var partitionManager = new InMemoryPartitionManager(); var ownershipList = new List <PartitionOwnership>(); var firstOwnership = new PartitionOwnership ( "namespace1", "eventHubName", "consumerGroup", "ownerIdentifier", "partitionId" ); ownershipList.Add(firstOwnership); await partitionManager.ClaimOwnershipAsync(ownershipList); // ETag must have been set by the partition manager. var eTag = firstOwnership.ETag; ownershipList.Clear(); var secondOwnership = new PartitionOwnership ( "namespace2", "eventHubName", "consumerGroup", "ownerIdentifier", "partitionId", eTag: eTag ); ownershipList.Add(secondOwnership); await partitionManager.ClaimOwnershipAsync(ownershipList); IEnumerable <PartitionOwnership> storedOwnership1 = await partitionManager.ListOwnershipAsync("namespace1", "eventHubName", "consumerGroup"); IEnumerable <PartitionOwnership> storedOwnership2 = await partitionManager.ListOwnershipAsync("namespace2", "eventHubName", "consumerGroup"); Assert.That(storedOwnership1, Is.Not.Null); Assert.That(storedOwnership1.Count, Is.EqualTo(1)); Assert.That(storedOwnership1.Single(), Is.EqualTo(firstOwnership)); Assert.That(storedOwnership2, Is.Not.Null); Assert.That(storedOwnership2.Count, Is.EqualTo(1)); Assert.That(storedOwnership2.Single(), Is.EqualTo(secondOwnership)); }
public async Task ClaimOwnershipAsyncCanClaimMultipleOwnership() { var partitionManager = new InMemoryPartitionManager(); var ownershipList = new List <PartitionOwnership>(); var ownershipCount = 5; for (int i = 0; i < ownershipCount; i++) { ownershipList.Add( new PartitionOwnership ( "eventHubName", "consumerGroup", "ownerIdentifier", $"partitionId { i }" )); } await partitionManager.ClaimOwnershipAsync(ownershipList); var storedOwnership = await partitionManager.ListOwnershipAsync("eventHubName", "consumerGroup"); Assert.That(storedOwnership, Is.Not.Null); Assert.That(storedOwnership.Count, Is.EqualTo(ownershipCount)); Assert.That(storedOwnership.OrderBy(ownership => ownership.PartitionId).SequenceEqual(ownershipList), Is.True); }
public async Task CheckpointUpdateUpdatesOwnershipInformation() { var partitionManager = new InMemoryPartitionManager(); var originalOwnership = new PartitionOwnership ("eventHubName", "consumerGroup", "ownerIdentifier", "partitionId", offset: 1, sequenceNumber: 2, lastModifiedTime: DateTimeOffset.UtcNow.Subtract(TimeSpan.FromMinutes(1))); await partitionManager.ClaimOwnershipAsync(new List <PartitionOwnership>() { originalOwnership }); // ETag must have been set by the partition manager. var originalLastModifiedTime = originalOwnership.LastModifiedTime; var originalETag = originalOwnership.ETag; await partitionManager.UpdateCheckpointAsync(new Checkpoint ("eventHubName", "consumerGroup", "ownerIdentifier", "partitionId", 10, 20)); // Make sure the ownership has changed, even though the instance should be the same. var storedOwnership = await partitionManager.ListOwnershipAsync("eventHubName", "consumerGroup"); Assert.That(storedOwnership, Is.Not.Null); Assert.That(storedOwnership.Count, Is.EqualTo(1)); Assert.That(storedOwnership.Single(), Is.EqualTo(originalOwnership)); Assert.That(originalOwnership.Offset, Is.EqualTo(10)); Assert.That(originalOwnership.SequenceNumber, Is.EqualTo(20)); Assert.That(originalOwnership.LastModifiedTime, Is.GreaterThan(originalLastModifiedTime)); Assert.That(originalOwnership.ETag, Is.Not.EqualTo(originalETag)); }
public async Task CheckpointUpdateFailsWhenOwnerChanges() { var partitionManager = new InMemoryPartitionManager(); var originalOwnership = new PartitionOwnership ("eventHubName", "consumerGroup", "ownerIdentifier1", "partitionId", offset: 1, sequenceNumber: 2, lastModifiedTime: DateTimeOffset.UtcNow); await partitionManager.ClaimOwnershipAsync(new List <PartitionOwnership>() { originalOwnership }); // ETag must have been set by the partition manager. var originalLastModifiedTime = originalOwnership.LastModifiedTime; var originalETag = originalOwnership.ETag; await partitionManager.UpdateCheckpointAsync(new Checkpoint ("eventHubName", "consumerGroup", "ownerIdentifier2", "partitionId", 10, 20)); // Make sure the ownership hasn't changed. var storedOwnership = await partitionManager.ListOwnershipAsync("eventHubName", "consumerGroup"); Assert.That(storedOwnership, Is.Not.Null); Assert.That(storedOwnership.Count, Is.EqualTo(1)); Assert.That(storedOwnership.Single(), Is.EqualTo(originalOwnership)); Assert.That(originalOwnership.OwnerIdentifier, Is.EqualTo("ownerIdentifier1")); Assert.That(originalOwnership.Offset, Is.EqualTo(1)); Assert.That(originalOwnership.SequenceNumber, Is.EqualTo(2)); Assert.That(originalOwnership.LastModifiedTime, Is.EqualTo(originalLastModifiedTime)); Assert.That(originalOwnership.ETag, Is.EqualTo(originalETag)); }
public async Task OwnershipClaimSucceedsWhenETagIsValid() { var partitionManager = new InMemoryPartitionManager(); var ownershipList = new List <PartitionOwnership>(); var firstOwnership = new PartitionOwnership ( "namespace", "eventHubName", "consumerGroup", "ownerIdentifier", "partitionId", offset: 1 ); ownershipList.Add(firstOwnership); await partitionManager.ClaimOwnershipAsync(ownershipList); // ETag must have been set by the partition manager. var eTag = firstOwnership.ETag; ownershipList.Clear(); var secondOwnership = new PartitionOwnership ( "namespace", "eventHubName", "consumerGroup", "ownerIdentifier", "partitionId", offset: 2, eTag: eTag ); ownershipList.Add(secondOwnership); await partitionManager.ClaimOwnershipAsync(ownershipList); IEnumerable <PartitionOwnership> storedOwnership = await partitionManager.ListOwnershipAsync("namespace", "eventHubName", "consumerGroup"); Assert.That(storedOwnership, Is.Not.Null); Assert.That(storedOwnership.Count, Is.EqualTo(1)); Assert.That(storedOwnership.Single(), Is.EqualTo(secondOwnership)); }
public async Task OwnershipClaimFailsWhenETagIsInvalid(string eTag) { var partitionManager = new InMemoryPartitionManager(); var ownershipList = new List <PartitionOwnership>(); var firstOwnership = new PartitionOwnership ( "eventHubName", "consumerGroup", "ownerIdentifier", "partitionId", offset: 1 ); ownershipList.Add(firstOwnership); await partitionManager.ClaimOwnershipAsync(ownershipList); ownershipList.Clear(); var secondOwnership = new PartitionOwnership ( "eventHubName", "consumerGroup", "ownerIdentifier", "partitionId", offset: 2, eTag: eTag ); ownershipList.Add(secondOwnership); await partitionManager.ClaimOwnershipAsync(ownershipList); var storedOwnership = await partitionManager.ListOwnershipAsync("eventHubName", "consumerGroup"); Assert.That(storedOwnership, Is.Not.Null); Assert.That(storedOwnership.Count, Is.EqualTo(1)); Assert.That(storedOwnership.Single(), Is.EqualTo(firstOwnership)); }
public async Task CheckpointUpdateDoesNotInterfereWithOtherPartitions() { var partitionManager = new InMemoryPartitionManager(); var ownership1 = new PartitionOwnership ("eventHubName", "consumerGroup", "ownerIdentifier", "partitionId1", offset: 1); var ownership2 = new PartitionOwnership ("eventHubName", "consumerGroup", "ownerIdentifier", "partitionId2", offset: 1); await partitionManager.ClaimOwnershipAsync(new List <PartitionOwnership>() { ownership1, ownership2 }); await partitionManager.UpdateCheckpointAsync(new Checkpoint ("eventHubName", "consumerGroup", "ownerIdentifier", "partitionId1", 10, 20)); Assert.That(ownership1.Offset, Is.EqualTo(10)); Assert.That(ownership2.Offset, Is.EqualTo(1)); }
public async Task FirstOwnershipClaimSucceeds() { var partitionManager = new InMemoryPartitionManager(); var ownershipList = new List <PartitionOwnership>(); var ownership = new PartitionOwnership ( "eventHubName", "consumerGroup", "ownerIdentifier", "partitionId" ); ownershipList.Add(ownership); await partitionManager.ClaimOwnershipAsync(ownershipList); var storedOwnership = await partitionManager.ListOwnershipAsync("eventHubName", "consumerGroup"); Assert.That(storedOwnership, Is.Not.Null); Assert.That(storedOwnership.Count, Is.EqualTo(1)); Assert.That(storedOwnership.Single(), Is.EqualTo(ownership)); }
public async Task EventProcessorCanReceiveFromCheckpointedEventPosition() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName); await using (var client = new EventHubClient(connectionString)) { int receivedEventsCount = 0; // Send some events. var expectedEventsCount = 20; var dummyEvent = new EventData(Encoding.UTF8.GetBytes("I'm dummy.")); long?checkpointedSequenceNumber = default; var partitionId = (await client.GetPartitionIdsAsync()).First(); await using (EventHubProducer producer = client.CreateProducer()) await using (EventHubConsumer consumer = client.CreateConsumer(EventHubConsumer.DefaultConsumerGroupName, partitionId, EventPosition.Earliest)) { // Send a few dummy events. We are not expecting to receive these. var dummyEventsCount = 30; for (int i = 0; i < dummyEventsCount; i++) { await producer.SendAsync(dummyEvent); } // Receive the events; because there is some non-determinism in the messaging flow, the // sent events may not be immediately available. Allow for a small number of attempts to receive, in order // to account for availability delays. var receivedEvents = new List <EventData>(); var index = 0; while ((receivedEvents.Count < dummyEventsCount) && (++index < ReceiveRetryLimit)) { receivedEvents.AddRange(await consumer.ReceiveAsync(dummyEventsCount + 10, TimeSpan.FromMilliseconds(25))); } Assert.That(receivedEvents.Count, Is.EqualTo(dummyEventsCount)); checkpointedSequenceNumber = receivedEvents.Last().SequenceNumber; // Send the events we expect to receive. for (int i = 0; i < expectedEventsCount; i++) { await producer.SendAsync(dummyEvent); } } // Create a partition manager and add an ownership with a checkpoint in it. var partitionManager = new InMemoryPartitionManager(); await partitionManager.ClaimOwnershipAsync(new List <PartitionOwnership>() { new PartitionOwnership(client.FullyQualifiedNamespace, client.EventHubName, EventHubConsumer.DefaultConsumerGroupName, "ownerIdentifier", partitionId, sequenceNumber: checkpointedSequenceNumber, lastModifiedTime: DateTimeOffset.UtcNow) }); // Create the event processor manager to manage our event processors. var eventProcessorManager = new EventProcessorManager ( EventHubConsumer.DefaultConsumerGroupName, client, partitionManager, onProcessEvents: (partitionContext, events, cancellationToken) => { // Make it a list so we can safely enumerate it. var eventsList = new List <EventData>(events ?? Enumerable.Empty <EventData>()); if (eventsList.Count > 0) { Interlocked.Add(ref receivedEventsCount, eventsList.Count); } } ); eventProcessorManager.AddEventProcessors(1); // Start the event processors. await eventProcessorManager.StartAllAsync(); // Make sure the event processors have enough time to stabilize and receive events. await eventProcessorManager.WaitStabilization(); // Stop the event processors. await eventProcessorManager.StopAllAsync(); // Validate results. Assert.That(receivedEventsCount, Is.EqualTo(expectedEventsCount)); } } }