Exemple #1
0
        async Task InvokeAfterReceiveTimeoutTrue()
        {
            const int ReceiveTimeoutInSeconds = 15;

            TestUtility.Log("Testing EventProcessorHost with InvokeProcessorAfterReceiveTimeout=true");

            var emptyBatchReceiveEvents = new ConcurrentDictionary <string, AsyncAutoResetEvent>();

            foreach (var partitionId in PartitionIds)
            {
                emptyBatchReceiveEvents[partitionId] = new AsyncAutoResetEvent(false);
            }

            var eventProcessorHost = new EventProcessorHost(
                string.Empty,
                PartitionReceiver.DefaultConsumerGroupName,
                TestUtility.EventHubsConnectionString,
                TestUtility.StorageConnectionString,
                this.LeaseContainerName);

            var processorOptions = new EventProcessorOptions
            {
                ReceiveTimeout = TimeSpan.FromSeconds(ReceiveTimeoutInSeconds),
                InvokeProcessorAfterReceiveTimeout = true,
                MaxBatchSize = 100
            };

            var processorFactory = new TestEventProcessorFactory();

            processorFactory.OnCreateProcessor += (f, createArgs) =>
            {
                var    processor   = createArgs.Item2;
                string partitionId = createArgs.Item1.PartitionId;
                processor.OnOpen          += (_, partitionContext) => TestUtility.Log($"Partition {partitionId} TestEventProcessor opened");
                processor.OnProcessEvents += (_, eventsArgs) =>
                {
                    int eventCount = eventsArgs.Item2.events != null?eventsArgs.Item2.events.Count() : 0;

                    TestUtility.Log($"Partition {partitionId} TestEventProcessor processing {eventCount} event(s)");
                    if (eventCount == 0)
                    {
                        var emptyBatchReceiveEvent = emptyBatchReceiveEvents[partitionId];
                        emptyBatchReceiveEvent.Set();
                    }
                };
            };

            await eventProcessorHost.RegisterEventProcessorFactoryAsync(processorFactory, processorOptions);

            try
            {
                TestUtility.Log("Waiting for each partition to receive an empty batch of events...");
                foreach (var partitionId in PartitionIds)
                {
                    var  emptyBatchReceiveEvent = emptyBatchReceiveEvents[partitionId];
                    bool emptyBatchReceived     = await emptyBatchReceiveEvent.WaitAsync(TimeSpan.FromSeconds(ReceiveTimeoutInSeconds * 2));

                    Assert.True(emptyBatchReceived, $"Partition {partitionId} didn't receive an empty batch!");
                }
            }
            finally
            {
                TestUtility.Log("Calling UnregisterEventProcessorAsync");
                await eventProcessorHost.UnregisterEventProcessorAsync();
            }
        }
Exemple #2
0
        async Task MultipleConsumerGroups()
        {
            var customConsumerGroupName = "cgroup1";

            var ehClient = EventHubClient.CreateFromConnectionString(TestUtility.EventHubsConnectionString);

            // Generate a new lease container name that will be used through out the test.
            string leaseContainerName = Guid.NewGuid().ToString();

            var consumerGroupNames = new[]  { PartitionReceiver.DefaultConsumerGroupName, customConsumerGroupName };
            var processorOptions   = new EventProcessorOptions
            {
                ReceiveTimeout = TimeSpan.FromSeconds(15),
                MaxBatchSize   = 100
            };
            var processorFactory       = new TestEventProcessorFactory();
            var partitionReceiveEvents = new ConcurrentDictionary <string, AsyncAutoResetEvent>();
            var hosts = new List <EventProcessorHost>();

            // Confirm that custom consumer group exists before starting hosts.
            try
            {
                // Create a receiver on the consumer group and try to receive.
                // Receive call will fail if consumer group is missing.
                var receiver = ehClient.CreateReceiver(customConsumerGroupName, this.PartitionIds.First(), PartitionReceiver.StartOfStream);
                await receiver.ReceiveAsync(1, TimeSpan.FromSeconds(5));
            }
            catch (MessagingEntityNotFoundException)
            {
                throw new Exception($"Cunsumer group {customConsumerGroupName} cannot be found. MultipleConsumerGroups unit test requires consumer group '{customConsumerGroupName}' to be created before running the test.");
            }

            processorFactory.OnCreateProcessor += (f, createArgs) =>
            {
                var    processor         = createArgs.Item2;
                string partitionId       = createArgs.Item1.PartitionId;
                string hostName          = createArgs.Item1.Owner;
                string consumerGroupName = createArgs.Item1.ConsumerGroupName;
                processor.OnOpen          += (_, partitionContext) => TestUtility.Log($"{hostName} > {consumerGroupName} > Partition {partitionId} TestEventProcessor opened");
                processor.OnClose         += (_, closeArgs) => TestUtility.Log($"{hostName} > {consumerGroupName} > Partition {partitionId} TestEventProcessor closing: {closeArgs.Item2}");
                processor.OnProcessError  += (_, errorArgs) => TestUtility.Log($"{hostName} > {consumerGroupName} > Partition {partitionId} TestEventProcessor process error {errorArgs.Item2.Message}");
                processor.OnProcessEvents += (_, eventsArgs) =>
                {
                    int eventCount = eventsArgs.Item2.events != null?eventsArgs.Item2.events.Count() : 0;

                    TestUtility.Log($"{hostName} > {consumerGroupName} > Partition {partitionId} TestEventProcessor processing {eventCount} event(s)");
                    if (eventCount > 0)
                    {
                        var receivedEvent = partitionReceiveEvents[consumerGroupName + "-" + partitionId];
                        receivedEvent.Set();
                    }
                };
            };

            try
            {
                // Register a new host for each consumer group.
                foreach (var consumerGroupName in consumerGroupNames)
                {
                    var eventProcessorHost = new EventProcessorHost(
                        string.Empty,
                        consumerGroupName,
                        TestUtility.EventHubsConnectionString,
                        TestUtility.StorageConnectionString,
                        leaseContainerName);

                    TestUtility.Log($"Calling RegisterEventProcessorAsync on consumer group {consumerGroupName}");

                    foreach (var partitionId in PartitionIds)
                    {
                        partitionReceiveEvents[consumerGroupName + "-" + partitionId] = new AsyncAutoResetEvent(false);
                    }

                    await eventProcessorHost.RegisterEventProcessorFactoryAsync(processorFactory, processorOptions);

                    hosts.Add(eventProcessorHost);
                }

                TestUtility.Log("Sending an event to each partition");
                var sendTasks = new List <Task>();
                foreach (var partitionId in PartitionIds)
                {
                    sendTasks.Add(TestUtility.SendToPartitionAsync(ehClient, partitionId, $"{partitionId} event."));
                }

                await Task.WhenAll(sendTasks);

                TestUtility.Log("Verifying an event was received by each partition for each consumer group");
                foreach (var consumerGroupName in consumerGroupNames)
                {
                    foreach (var partitionId in PartitionIds)
                    {
                        var  receivedEvent            = partitionReceiveEvents[consumerGroupName + "-" + partitionId];
                        bool partitionReceivedMessage = await receivedEvent.WaitAsync(TimeSpan.FromSeconds(30));

                        Assert.True(partitionReceivedMessage, $"ConsumerGroup {consumerGroupName} > Partition {partitionId} didn't receive any message!");
                    }
                }

                TestUtility.Log("Success");
            }
            finally
            {
                TestUtility.Log("Calling UnregisterEventProcessorAsync on both hosts.");
                foreach (var eph in hosts)
                {
                    await eph.UnregisterEventProcessorAsync();
                }
            }
        }
Exemple #3
0
        async Task MultipleProcessorHosts()
        {
            int hostCount = 3;

            TestUtility.Log($"Testing with {hostCount} EventProcessorHost instances");

            // Prepare partition trackers.
            var partitionReceiveEvents = new ConcurrentDictionary <string, AsyncAutoResetEvent>();

            foreach (var partitionId in PartitionIds)
            {
                partitionReceiveEvents[partitionId] = new AsyncAutoResetEvent(false);
            }

            // Prepare host trackers.
            var hostReceiveEvents = new ConcurrentDictionary <string, AsyncAutoResetEvent>();

            var hosts = new List <EventProcessorHost>();

            try
            {
                for (int hostId = 0; hostId < hostCount; hostId++)
                {
                    var thisHostName = $"host-{hostId}";
                    hostReceiveEvents[thisHostName] = new AsyncAutoResetEvent(false);

                    TestUtility.Log("Creating EventProcessorHost");
                    var eventProcessorHost = new EventProcessorHost(
                        thisHostName,
                        string.Empty, // Passing empty as entity path here rsince path is already in EH connection string.
                        PartitionReceiver.DefaultConsumerGroupName,
                        TestUtility.EventHubsConnectionString,
                        TestUtility.StorageConnectionString,
                        this.LeaseContainerName);
                    hosts.Add(eventProcessorHost);
                    TestUtility.Log($"Calling RegisterEventProcessorAsync");
                    var processorOptions = new EventProcessorOptions
                    {
                        ReceiveTimeout = TimeSpan.FromSeconds(10),
                        InvokeProcessorAfterReceiveTimeout = true,
                        MaxBatchSize = 100
                    };

                    var processorFactory = new TestEventProcessorFactory();
                    processorFactory.OnCreateProcessor += (f, createArgs) =>
                    {
                        var    processor   = createArgs.Item2;
                        string partitionId = createArgs.Item1.PartitionId;
                        string hostName    = createArgs.Item1.Owner;
                        processor.OnOpen          += (_, partitionContext) => TestUtility.Log($"{hostName} > Partition {partitionId} TestEventProcessor opened");
                        processor.OnClose         += (_, closeArgs) => TestUtility.Log($"{hostName} > Partition {partitionId} TestEventProcessor closing: {closeArgs.Item2}");
                        processor.OnProcessError  += (_, errorArgs) => TestUtility.Log($"{hostName} > Partition {partitionId} TestEventProcessor process error {errorArgs.Item2.Message}");
                        processor.OnProcessEvents += (_, eventsArgs) =>
                        {
                            int eventCount = eventsArgs.Item2.events != null?eventsArgs.Item2.events.Count() : 0;

                            if (eventCount > 0)
                            {
                                TestUtility.Log($"{hostName} > Partition {partitionId} TestEventProcessor processing {eventCount} event(s)");
                                partitionReceiveEvents[partitionId].Set();
                                hostReceiveEvents[hostName].Set();
                            }
                        };
                    };

                    await eventProcessorHost.RegisterEventProcessorFactoryAsync(processorFactory, processorOptions);
                }

                // Allow some time for each host to own at least 1 partition.
                // Partition stealing logic balances partition ownership one at a time.
                TestUtility.Log("Waiting for partition ownership to settle...");
                await Task.Delay(TimeSpan.FromSeconds(60));

                TestUtility.Log("Sending an event to each partition");
                var ehClient  = EventHubClient.CreateFromConnectionString(TestUtility.EventHubsConnectionString);
                var sendTasks = new List <Task>();
                foreach (var partitionId in PartitionIds)
                {
                    sendTasks.Add(TestUtility.SendToPartitionAsync(ehClient, partitionId, $"{partitionId} event."));
                }
                await Task.WhenAll(sendTasks);

                TestUtility.Log("Verifying an event was received by each partition");
                foreach (var e in partitionReceiveEvents)
                {
                    bool ret = await e.Value.WaitAsync(TimeSpan.FromSeconds(30));

                    Assert.True(ret, $"Partition {e.Key} didn't receive any message!");
                }

                TestUtility.Log("Verifying at least an event was received by each host");
                foreach (var e in hostReceiveEvents)
                {
                    bool ret = await e.Value.WaitAsync(TimeSpan.FromSeconds(30));

                    Assert.True(ret, $"Host {e.Key} didn't receive any message!");
                }
            }
            finally
            {
                var shutdownTasks = new List <Task>();
                foreach (var host in hosts)
                {
                    TestUtility.Log($"Host {host} Calling UnregisterEventProcessorAsync.");
                    shutdownTasks.Add(host.UnregisterEventProcessorAsync());
                }

                await Task.WhenAll(shutdownTasks);
            }
        }