Example #1
0
        public async Task CheckpointUpdateDoesNotInterfereWithOtherNamespaces()
        {
            var storageManager = new MockCheckPointStorage();

            var mockEvent = new MockEventData(
                eventBody: Array.Empty <byte>(),
                offset: 10,
                sequenceNumber: 20);

            await storageManager.UpdateCheckpointAsync(new EventProcessorCheckpoint
            {
                FullyQualifiedNamespace = "namespace1",
                EventHubName            = "eventHubName",
                ConsumerGroup           = "consumerGroup",
                PartitionId             = "partitionId"
            }, mockEvent);

            await storageManager.UpdateCheckpointAsync(new EventProcessorCheckpoint
            {
                FullyQualifiedNamespace = "namespace2",
                EventHubName            = "eventHubName",
                ConsumerGroup           = "consumerGroup",
                PartitionId             = "partitionId"
            }, mockEvent);

            IEnumerable <EventProcessorCheckpoint> storedCheckpointsList1 = await storageManager.ListCheckpointsAsync("namespace1", "eventHubName", "consumerGroup");

            IEnumerable <EventProcessorCheckpoint> storedCheckpointsList2 = await storageManager.ListCheckpointsAsync("namespace2", "eventHubName", "consumerGroup");

            Assert.That(storedCheckpointsList1, Is.Not.Null);
            Assert.That(storedCheckpointsList1.Count, Is.EqualTo(1));

            Assert.That(storedCheckpointsList2, Is.Not.Null);
            Assert.That(storedCheckpointsList2.Count, Is.EqualTo(1));
        }
Example #2
0
        public async Task ListOwnershipAsyncReturnsEmptyIEnumerableWhenThereAreNoOwnership()
        {
            var partitionManager = new MockCheckPointStorage();
            IEnumerable <PartitionOwnership> ownership = await partitionManager.ListOwnershipAsync("namespace", "eventHubName", "consumerGroup");

            Assert.That(ownership, Is.Not.Null.And.Empty);
        }
Example #3
0
        public async Task CheckpointUpdateUpdatesOwnershipInformation()
        {
            var partitionManager  = new MockCheckPointStorage();
            var originalOwnership = new PartitionOwnership
                                        ("namespace", "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.

            DateTimeOffset?originalLastModifiedTime = originalOwnership.LastModifiedTime;
            var            originalETag             = originalOwnership.ETag;

            await partitionManager.UpdateCheckpointAsync(new Checkpoint
                                                         ("namespace", "eventHubName", "consumerGroup", "ownerIdentifier", "partitionId", 10, 20));

            // Make sure the ownership has changed, even though the instance should be the same.

            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(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));
        }
Example #4
0
        public async Task CheckpointUpdateFailsWhenOwnerChanges()
        {
            var partitionManager  = new MockCheckPointStorage();
            var originalOwnership = new PartitionOwnership
                                        ("namespace", "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.

            DateTimeOffset?originalLastModifiedTime = originalOwnership.LastModifiedTime;
            var            originalETag             = originalOwnership.ETag;

            await partitionManager.UpdateCheckpointAsync(new Checkpoint
                                                         ("namespace", "eventHubName", "consumerGroup", "ownerIdentifier2", "partitionId", 10, 20));

            // Make sure the ownership hasn't changed.

            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(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));
        }
Example #5
0
        public async Task ClaimOwnershipAsyncCanClaimMultipleOwnership()
        {
            var partitionManager = new MockCheckPointStorage();
            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);

            IEnumerable <PartitionOwnership> storedOwnership = await partitionManager.ListOwnershipAsync("namespace", "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);
        }
Example #6
0
        public async Task CheckpointUpdateDoesNotInterfereWithOtherPartitions()
        {
            var storageManager = new MockCheckPointStorage();

            await storageManager.UpdateCheckpointAsync(new EventProcessorCheckpoint
            {
                FullyQualifiedNamespace = "namespace",
                EventHubName            = "eventHubName",
                ConsumerGroup           = "consumerGroup",
                PartitionId             = "partitionId1",
                Offset         = 10,
                SequenceNumber = 20
            });

            await storageManager.UpdateCheckpointAsync(new EventProcessorCheckpoint
            {
                FullyQualifiedNamespace = "namespace",
                EventHubName            = "eventHubName",
                ConsumerGroup           = "consumerGroup",
                PartitionId             = "partitionId2",
                Offset         = 10,
                SequenceNumber = 20
            });

            IEnumerable <EventProcessorCheckpoint> storedCheckpointsList = await storageManager.ListCheckpointsAsync("namespace", "eventHubName", "consumerGroup");

            Assert.That(storedCheckpointsList, Is.Not.Null);
            Assert.That(storedCheckpointsList.Count, Is.EqualTo(2));

            EventProcessorCheckpoint storedCheckpoint1 = storedCheckpointsList.First(checkpoint => checkpoint.PartitionId == "partitionId1");
            EventProcessorCheckpoint storedCheckpoint2 = storedCheckpointsList.First(checkpoint => checkpoint.PartitionId == "partitionId2");

            Assert.That(storedCheckpoint1, Is.Not.Null);
            Assert.That(storedCheckpoint2, Is.Not.Null);
        }
Example #7
0
        public async Task CheckpointUpdateFailsWhenAssociatedOwnershipDoesNotExist()
        {
            var partitionManager = new MockCheckPointStorage();

            await partitionManager.UpdateCheckpointAsync(new Checkpoint
                                                         ("namespace", "eventHubName", "consumerGroup", "ownerIdentifier", "partitionId", offset : 10, sequenceNumber : 20));

            IEnumerable <PartitionOwnership> storedOwnership = await partitionManager.ListOwnershipAsync("namespace", "eventHubName", "consumerGroup");

            Assert.That(storedOwnership, Is.Not.Null);
            Assert.That(storedOwnership, Is.Empty);
        }
Example #8
0
        public async Task ClaimOwnershipAsyncReturnsOnlyTheSuccessfullyClaimedOwnership()
        {
            var partitionManager = new MockCheckPointStorage();
            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);
        }
Example #9
0
        public async Task ClaimOwnershipAsyncReturnsOnlyTheSuccessfullyClaimedOwnership()
        {
            var storageManager = new MockCheckPointStorage();
            var ownershipList  = new List <EventProcessorPartitionOwnership>();
            var ownershipCount = 5;

            for (int i = 0; i < ownershipCount; i++)
            {
                ownershipList.Add(
                    new EventProcessorPartitionOwnership
                {
                    FullyQualifiedNamespace = "namespace",
                    EventHubName            = "eventHubName",
                    ConsumerGroup           = "consumerGroup",
                    OwnerIdentifier         = "ownerIdentifier",
                    PartitionId             = $"{ i }"
                });
            }

            await storageManager.ClaimOwnershipAsync(ownershipList);

            // The versions must have been set by the storage manager.

            var versions = ownershipList.Select(ownership => ownership.Version).ToList();

            ownershipList.Clear();

            // Use a valid version 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 EventProcessorPartitionOwnership
                {
                    FullyQualifiedNamespace = "namespace",
                    EventHubName            = "eventHubName",
                    ConsumerGroup           = "consumerGroup",
                    OwnerIdentifier         = "ownerIdentifier",
                    PartitionId             = $"{ i }",
                    Version = i % 2 == 1 ? versions[i] : null
                });
            }

            IEnumerable <EventProcessorPartitionOwnership> claimedOwnership = await storageManager.ClaimOwnershipAsync(ownershipList);

            Assert.That(claimedOwnership, Is.Not.Null);
            Assert.That(claimedOwnership.Count, Is.EqualTo(expectedClaimedCount));
            Assert.That(claimedOwnership.OrderBy(ownership => int.Parse(ownership.PartitionId)).SequenceEqual(ownershipList.Where(ownership => int.Parse(ownership.PartitionId) % 2 == 1)), Is.True);
        }
Example #10
0
        public async Task OwnershipClaimDoesNotInterfereWithOtherNamespaces()
        {
            var partitionManager = new MockCheckPointStorage();
            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));
        }
Example #11
0
        public async Task OwnershipClaimDoesNotInterfereWithOtherNamespaces()
        {
            var storageManager = new MockCheckPointStorage();
            var ownershipList  = new List <EventProcessorPartitionOwnership>();

            var firstOwnership = new EventProcessorPartitionOwnership
            {
                FullyQualifiedNamespace = "namespace1",
                EventHubName            = "eventHubName",
                ConsumerGroup           = "consumerGroup",
                OwnerIdentifier         = "ownerIdentifier",
                PartitionId             = "partitionId"
            };

            ownershipList.Add(firstOwnership);

            await storageManager.ClaimOwnershipAsync(ownershipList);

            // Version must have been set by the storage manager.

            var version = firstOwnership.Version;

            ownershipList.Clear();

            var secondOwnership = new EventProcessorPartitionOwnership
            {
                FullyQualifiedNamespace = "namespace2",
                EventHubName            = "eventHubName",
                ConsumerGroup           = "consumerGroup",
                OwnerIdentifier         = "ownerIdentifier",
                PartitionId             = "partitionId",
                Version = version
            };

            ownershipList.Add(secondOwnership);

            await storageManager.ClaimOwnershipAsync(ownershipList);

            IEnumerable <EventProcessorPartitionOwnership> storedOwnership1 = await storageManager.ListOwnershipAsync("namespace1", "eventHubName", "consumerGroup");

            IEnumerable <EventProcessorPartitionOwnership> storedOwnership2 = await storageManager.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));
        }
Example #12
0
        public async Task OwnershipClaimSucceedsWhenETagIsValid()
        {
            var partitionManager = new MockCheckPointStorage();
            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));
        }
Example #13
0
        public async Task CheckpointUpdateDoesNotInterfereWithOtherNamespaces()
        {
            var partitionManager = new MockCheckPointStorage();

            await partitionManager.UpdateCheckpointAsync(new Checkpoint
                                                         ("namespace1", "eventHubName", "consumerGroup", "partitionId", 10, 20));

            await partitionManager.UpdateCheckpointAsync(new Checkpoint
                                                         ("namespace2", "eventHubName", "consumerGroup", "partitionId", 10, 20));

            IEnumerable <Checkpoint> storedCheckpointsList1 = await partitionManager.ListCheckpointsAsync("namespace1", "eventHubName", "consumerGroup");

            IEnumerable <Checkpoint> storedCheckpointsList2 = await partitionManager.ListCheckpointsAsync("namespace2", "eventHubName", "consumerGroup");

            Assert.That(storedCheckpointsList1, Is.Not.Null);
            Assert.That(storedCheckpointsList1.Count, Is.EqualTo(1));

            Assert.That(storedCheckpointsList2, Is.Not.Null);
            Assert.That(storedCheckpointsList2.Count, Is.EqualTo(1));
        }
Example #14
0
        public async Task OwnershipClaimFailsWhenETagIsInvalid(string eTag)
        {
            var partitionManager = new MockCheckPointStorage();
            var ownershipList    = new List <PartitionOwnership>();
            var firstOwnership   =
                new PartitionOwnership
                (
                    "namespace",
                    "eventHubName",
                    "consumerGroup",
                    "ownerIdentifier",
                    "partitionId"
                );

            ownershipList.Add(firstOwnership);

            await partitionManager.ClaimOwnershipAsync(ownershipList);

            ownershipList.Clear();

            var secondOwnership =
                new PartitionOwnership
                (
                    "namespace",
                    "eventHubName",
                    "consumerGroup",
                    "ownerIdentifier",
                    "partitionId",
                    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(firstOwnership));
        }
Example #15
0
        public async Task CheckpointUpdateDoesNotInterfereWithOtherPartitions()
        {
            var partitionManager = new MockCheckPointStorage();

            var ownership1 = new PartitionOwnership
                                 ("namespace", "eventHubName", "consumerGroup", "ownerIdentifier", "partitionId1", offset: 1);
            var ownership2 = new PartitionOwnership
                                 ("namespace", "eventHubName", "consumerGroup", "ownerIdentifier", "partitionId2", offset: 1);

            await partitionManager.ClaimOwnershipAsync(new List <PartitionOwnership>()
            {
                ownership1,
                ownership2
            });

            await partitionManager.UpdateCheckpointAsync(new Checkpoint
                                                         ("namespace", "eventHubName", "consumerGroup", "ownerIdentifier", "partitionId1", 10, 20));

            Assert.That(ownership1.Offset, Is.EqualTo(10));
            Assert.That(ownership2.Offset, Is.EqualTo(1));
        }
Example #16
0
        public async Task CheckpointUpdateDoesNotInterfereWithOtherPartitions()
        {
            var partitionManager = new MockCheckPointStorage();

            await partitionManager.UpdateCheckpointAsync(new Checkpoint
                                                         ("namespace", "eventHubName", "consumerGroup", "partitionId1", 10, 20));

            await partitionManager.UpdateCheckpointAsync(new Checkpoint
                                                         ("namespace", "eventHubName", "consumerGroup", "partitionId2", 10, 20));

            IEnumerable <Checkpoint> storedCheckpointsList = await partitionManager.ListCheckpointsAsync("namespace", "eventHubName", "consumerGroup");

            Assert.That(storedCheckpointsList, Is.Not.Null);
            Assert.That(storedCheckpointsList.Count, Is.EqualTo(2));

            Checkpoint storedCheckpoint1 = storedCheckpointsList.First(checkpoint => checkpoint.PartitionId == "partitionId1");
            Checkpoint storedCheckpoint2 = storedCheckpointsList.First(checkpoint => checkpoint.PartitionId == "partitionId2");

            Assert.That(storedCheckpoint1, Is.Not.Null);
            Assert.That(storedCheckpoint2, Is.Not.Null);
        }
Example #17
0
        public async Task OwnershipClaimFailsWhenVersionIsInvalid(string version)
        {
            var storageManager = new MockCheckPointStorage();
            var ownershipList  = new List <EventProcessorPartitionOwnership>();
            var firstOwnership = new EventProcessorPartitionOwnership
            {
                FullyQualifiedNamespace = "namespace",
                EventHubName            = "eventHubName",
                ConsumerGroup           = "consumerGroup",
                OwnerIdentifier         = "ownerIdentifier",
                PartitionId             = "partitionId"
            };

            ownershipList.Add(firstOwnership);

            await storageManager.ClaimOwnershipAsync(ownershipList);

            ownershipList.Clear();

            var secondOwnership = new EventProcessorPartitionOwnership
            {
                FullyQualifiedNamespace = "namespace",
                EventHubName            = "eventHubName",
                ConsumerGroup           = "consumerGroup",
                OwnerIdentifier         = "ownerIdentifier",
                PartitionId             = "partitionId",
                Version = version
            };

            ownershipList.Add(secondOwnership);

            await storageManager.ClaimOwnershipAsync(ownershipList);

            IEnumerable <EventProcessorPartitionOwnership> storedOwnership = await storageManager.ListOwnershipAsync("namespace", "eventHubName", "consumerGroup");

            Assert.That(storedOwnership, Is.Not.Null);
            Assert.That(storedOwnership.Count, Is.EqualTo(1));
            Assert.That(storedOwnership.Single(), Is.EqualTo(firstOwnership));
        }
Example #18
0
        public async Task FirstOwnershipClaimSucceeds()
        {
            var partitionManager = new MockCheckPointStorage();
            var ownershipList    = new List <PartitionOwnership>();
            var ownership        =
                new PartitionOwnership
                (
                    "namespace",
                    "eventHubName",
                    "consumerGroup",
                    "ownerIdentifier",
                    "partitionId"
                );

            ownershipList.Add(ownership);

            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(ownership));
        }
Example #19
0
        public async Task EventProcessorCanReceiveFromCheckpointedEventPosition()
        {
            await using (EventHubScope scope = await EventHubScope.CreateAsync(1))
            {
                var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName);

                await using (var connection = new EventHubConnection(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 connection.GetPartitionIdsAsync(DefaultRetryPolicy)).First();

                    await using (var producer = new EventHubProducerClient(connectionString))
                        await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connection))
                        {
                            // 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))
                            {
                                // TODO: Convert to iterator
                                //receivedEvents.AddRange(await receiver.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 MockCheckPointStorage();

                    await partitionManager.ClaimOwnershipAsync(new List <PartitionOwnership>()
                    {
                        new PartitionOwnership(connection.FullyQualifiedNamespace, connection.EventHubName,
                                               EventHubConsumerClient.DefaultConsumerGroupName, "ownerIdentifier", partitionId,
                                               lastModifiedTime: DateTimeOffset.UtcNow)
                    });

                    // Create the event processor manager to manage our event processors.

                    var eventProcessorManager = new EventProcessorManager
                                                (
                        EventHubConsumerClient.DefaultConsumerGroupName,
                        connectionString,
                        partitionManager,
                        onProcessEvent: eventArgs =>
                    {
                        if (eventArgs.Data != null)
                        {
                            Interlocked.Increment(ref receivedEventsCount);
                        }
                    }
                                                );

                    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));
                }
            }
        }
        public async Task PartitionProcessorCanCreateACheckpoint()
        {
            await using (EventHubScope scope = await EventHubScope.CreateAsync(1))
            {
                var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName);

                await using (var connection = new EventHubConnection(connectionString))
                {
                    // Send some events.

                    EventData lastEvent;

                    await using (var producer = new EventHubProducerClient(connection))
                        await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString))
                        {
                            // Send a few events.  We are only interested in the last one of them.

                            var dummyEventsCount = 10;

                            using (var dummyBatch = await producer.CreateBatchAsync())
                            {
                                for (int i = 0; i < dummyEventsCount; i++)
                                {
                                    dummyBatch.TryAdd(new EventData(Encoding.UTF8.GetBytes("I'm dummy.")));
                                }

                                await producer.SendAsync(dummyBatch);
                            }

                            // 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))
                            {
                                Assert.Fail("Convert to iterator.");
                                //receivedEvents.AddRange(await receiver.ReceiveAsync(dummyEventsCount + 10, TimeSpan.FromMilliseconds(25)));
                            }

                            Assert.That(receivedEvents.Count, Is.EqualTo(dummyEventsCount));

                            lastEvent = receivedEvents.Last();
                        }

                    // Create a storage manager so we can retrieve the created checkpoint from it.

                    var storageManager = new MockCheckPointStorage();

                    // Create the event processor manager to manage our event processors.

                    var eventProcessorManager = new EventProcessorManager
                                                (
                        EventHubConsumerClient.DefaultConsumerGroupName,
                        connectionString,
                        storageManager,
                        onProcessEvent: eventArgs =>
                    {
                        if (eventArgs.Data != null)
                        {
                            eventArgs.UpdateCheckpointAsync();
                        }
                    }
                                                );

                    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.

                    IEnumerable <PartitionOwnership> ownershipEnumerable = await storageManager.ListOwnershipAsync(connection.FullyQualifiedNamespace, connection.EventHubName, EventHubConsumerClient.DefaultConsumerGroupName);

                    Assert.That(ownershipEnumerable, Is.Not.Null);
                    Assert.That(ownershipEnumerable.Count, Is.EqualTo(1));
                }
            }
        }
Example #21
0
        public async Task ProcessorDoesNotProcessCheckpointedEventsAgain()
        {
            await using (EventHubScope scope = await EventHubScope.CreateAsync(1))
            {
                var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName);

                var firstEventBatch = Enumerable
                                      .Range(0, 20)
                                      .Select(index => new EventData(Encoding.UTF8.GetBytes($"First event batch: { index }")))
                                      .ToList();

                var secondEventBatch = Enumerable
                                       .Range(0, 10)
                                       .Select(index => new EventData(Encoding.UTF8.GetBytes($"Second event batch: { index }")))
                                       .ToList();

                var completionSource = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);
                var firstBatchReceivedEventsCount = 0;

                // Send the first batch of events and checkpoint after the last one.

                var checkpointStorage = new MockCheckPointStorage();
                var firstProcessor    = new EventProcessorClient(checkpointStorage, EventHubConsumerClient.DefaultConsumerGroupName,
                                                                 TestEnvironment.FullyQualifiedNamespace, scope.EventHubName, () => new EventHubConnection(connectionString), default);

                firstProcessor.ProcessEventAsync += async eventArgs =>
                {
                    if (++firstBatchReceivedEventsCount == firstEventBatch.Count)
                    {
                        await eventArgs.UpdateCheckpointAsync();

                        completionSource.SetResult(true);
                    }
                };

                firstProcessor.ProcessErrorAsync += eventArgs => Task.CompletedTask;

                await using (var producer = new EventHubProducerClient(connectionString))
                {
                    using var batch = await producer.CreateBatchAsync();

                    foreach (var eventData in firstEventBatch)
                    {
                        batch.TryAdd(eventData);
                    }

                    await producer.SendAsync(batch);
                }

                // Establish timed cancellation to ensure that the test doesn't hang.

                using var cancellationSource = new CancellationTokenSource();
                cancellationSource.CancelAfter(TimeSpan.FromMinutes(5));

                await firstProcessor.StartProcessingAsync(cancellationSource.Token);

                while (!completionSource.Task.IsCompleted &&
                       !cancellationSource.IsCancellationRequested)
                {
                    await Task.Delay(25);
                }

                await firstProcessor.StopProcessingAsync(cancellationSource.Token);

                // Send the second batch of events. Only the new events should be read by the second processor.

                await using (var producer = new EventHubProducerClient(connectionString))
                {
                    using var batch = await producer.CreateBatchAsync();

                    foreach (var eventData in secondEventBatch)
                    {
                        batch.TryAdd(eventData);
                    }

                    await producer.SendAsync(batch);
                }

                completionSource = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);
                var secondBatchReceivedEvents = new List <EventData>();

                var secondProcessor = new EventProcessorClient(checkpointStorage, EventHubConsumerClient.DefaultConsumerGroupName,
                                                               TestEnvironment.FullyQualifiedNamespace, scope.EventHubName, () => new EventHubConnection(connectionString), default);

                secondProcessor.ProcessEventAsync += eventArgs =>
                {
                    secondBatchReceivedEvents.Add(eventArgs.Data);

                    if (secondBatchReceivedEvents.Count == firstEventBatch.Count)
                    {
                        completionSource.SetResult(true);
                    }

                    return(Task.CompletedTask);
                };

                var wasErrorHandlerCalled = false;

                secondProcessor.ProcessErrorAsync += eventArgs =>
                {
                    wasErrorHandlerCalled = true;
                    return(Task.CompletedTask);
                };

                await secondProcessor.StartProcessingAsync(cancellationSource.Token);

                while (!completionSource.Task.IsCompleted &&
                       !cancellationSource.IsCancellationRequested)
                {
                    await Task.Delay(25);
                }

                await secondProcessor.StopProcessingAsync(cancellationSource.Token);

                Assert.That(cancellationSource.IsCancellationRequested, Is.False, "The processors should have stopped without cancellation.");
                Assert.That(wasErrorHandlerCalled, Is.False, "No errors should have happened while resuming from checkpoint.");

                var index = 0;

                foreach (var eventData in secondBatchReceivedEvents)
                {
                    Assert.That(eventData.IsEquivalentTo(secondEventBatch[index]), Is.True, "The received and sent event datas do not match.");
                    index++;
                }

                Assert.That(index, Is.EqualTo(secondEventBatch.Count), $"The second processor did not receive the expected amount of events.");
            }
        }
Example #22
0
        public async Task PartitionProcessorCanCreateACheckpoint()
        {
            await using EventHubScope scope = await EventHubScope.CreateAsync(1);

            var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName);

            await using var connection = new EventHubConnection(connectionString);
            // Send some events.

            EventData lastEvent;

            await using var producer = new EventHubProducerClient(connection);
            await using var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString);

            // Send a few events.  We are only interested in the last one of them.

            var dummyEventsCount = 10;

            using var dummyBatch = await producer.CreateBatchAsync();

            for (int i = 0; i < dummyEventsCount; i++)
            {
                dummyBatch.TryAdd(new EventData(Encoding.UTF8.GetBytes(eventBody)));
            }

            await producer.SendAsync(dummyBatch);

            var receivedEvents = new List <EventData>();

            using var cancellationSource = new CancellationTokenSource();
            cancellationSource.CancelAfter(TimeSpan.FromSeconds(30));

            await foreach (var evt in consumer.ReadEventsAsync(new ReadEventOptions {
                MaximumWaitTime = TimeSpan.FromSeconds(30)
            }, cancellationSource.Token))
            {
                receivedEvents.Add(evt.Data);
                if (receivedEvents.Count == dummyEventsCount)
                {
                    break;
                }
            }

            Assert.That(receivedEvents.Count, Is.EqualTo(dummyEventsCount));

            lastEvent = receivedEvents.Last();

            // Create a storage manager so we can retrieve the created checkpoint from it.

            var storageManager = new MockCheckPointStorage();

            // Create the event processor manager to manage our event processors.

            var eventProcessorManager = new EventProcessorManager
                                        (
                EventHubConsumerClient.DefaultConsumerGroupName,
                connectionString,
                storageManager,
                onProcessEvent: eventArgs =>
            {
                if (eventArgs.Data != null)
                {
                    eventArgs.UpdateCheckpointAsync();
                }
            }
                                        );

            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.

            IEnumerable <EventProcessorPartitionOwnership> ownershipEnumerable = await storageManager.ListOwnershipAsync(connection.FullyQualifiedNamespace, connection.EventHubName, EventHubConsumerClient.DefaultConsumerGroupName);

            Assert.That(ownershipEnumerable, Is.Not.Null);
            Assert.That(ownershipEnumerable.Count, Is.EqualTo(1));
        }