示例#1
0
        public void ClaimOwnershipForMissingPartitionLogsClaimOwnershipError()
        {
            var partitionOwnership = new List <EventProcessorPartitionOwnership>
            {
                new EventProcessorPartitionOwnership
                {
                    FullyQualifiedNamespace = FullyQualifiedNamespace,
                    EventHubName            = EventHubName,
                    ConsumerGroup           = ConsumerGroup,
                    OwnerIdentifier         = OwnershipIdentifier,
                    PartitionId             = PartitionId,
                    LastModifiedTime        = DateTime.UtcNow,
                    Version = MatchingEtag
                }
            };

            var mockBlobContainerClient = new MockBlobContainerClient().AddBlobClient($"{FullyQualifiedNamespace}/{EventHubName}/{ConsumerGroup}/ownership/1", _ => { });
            var target = new BlobsCheckpointStore(mockBlobContainerClient, DefaultRetryPolicy);

            var mockLog = new Mock <BlobEventStoreEventSource>();

            target.Logger = mockLog.Object;

            Assert.That(async() => await target.ClaimOwnershipAsync(partitionOwnership, CancellationToken.None), Throws.InstanceOf <RequestFailedException>());
            mockLog.Verify(m => m.ClaimOwnershipError(PartitionId, FullyQualifiedNamespace, EventHubName, ConsumerGroup, OwnershipIdentifier, It.Is <string>(e => e.Contains(BlobErrorCode.BlobNotFound.ToString()))));
        }
示例#2
0
        public void UpdateCheckpointLogsErrorsWhenTheBlobDoesNotExist()
        {
            var checkpoint = new EventProcessorCheckpoint
            {
                FullyQualifiedNamespace = FullyQualifiedNamespace,
                EventHubName            = EventHubName,
                ConsumerGroup           = ConsumerGroup,
                PartitionId             = PartitionId,
            };

            var expectedException = new DllNotFoundException("BOOM!");
            var mockLog           = new Mock <BlobEventStoreEventSource>();

            var mockContainerClient = new MockBlobContainerClient().AddBlobClient($"{FullyQualifiedNamespace}/{EventHubName}/{ConsumerGroup}/checkpoint/1", client =>
            {
                client.UploadBlobException = expectedException;
            });

            var target = new BlobsCheckpointStore(mockContainerClient, DefaultRetryPolicy);

            target.Logger = mockLog.Object;

            Assert.That(async() => await target.UpdateCheckpointAsync(checkpoint, new EventData(Array.Empty <byte>()), CancellationToken.None), Throws.Exception.EqualTo(expectedException));
            mockLog.Verify(log => log.UpdateCheckpointError(checkpoint.PartitionId, checkpoint.FullyQualifiedNamespace, checkpoint.EventHubName, checkpoint.ConsumerGroup, expectedException.Message));
        }
示例#3
0
        public void ClaimOwnershipLogsErrors()
        {
            var partitionOwnership = new List <EventProcessorPartitionOwnership>
            {
                new EventProcessorPartitionOwnership
                {
                    FullyQualifiedNamespace = FullyQualifiedNamespace,
                    EventHubName            = EventHubName,
                    ConsumerGroup           = ConsumerGroup,
                    OwnerIdentifier         = OwnershipIdentifier,
                    PartitionId             = PartitionId,
                    LastModifiedTime        = DateTime.UtcNow
                }
            };

            var expectedException   = new DllNotFoundException("BOOM!");
            var mockLog             = new Mock <BlobEventStoreEventSource>();
            var mockContainerClient = new MockBlobContainerClient().AddBlobClient($"{FullyQualifiedNamespace}/{EventHubName}/{ConsumerGroup}/ownership/1", client => client.UploadBlobException = expectedException);

            var target = new BlobsCheckpointStore(mockContainerClient, DefaultRetryPolicy);

            target.Logger = mockLog.Object;

            Assert.That(async() => await target.ClaimOwnershipAsync(partitionOwnership, CancellationToken.None), Throws.Exception.EqualTo(expectedException));
            mockLog.Verify(m => m.ClaimOwnershipError(PartitionId, FullyQualifiedNamespace, EventHubName, ConsumerGroup, OwnershipIdentifier, expectedException.Message));
        }
示例#4
0
        public async Task ClaimOwnershipForExistingPartitionWithWrongEtagLogsOwnershipNotClaimable()
        {
            var blobInfo = BlobsModelFactory.BlobInfo(new ETag($@"""{WrongEtag}"""), DateTime.UtcNow);

            var partitionOwnership = new List <EventProcessorPartitionOwnership>
            {
                new EventProcessorPartitionOwnership
                {
                    FullyQualifiedNamespace = FullyQualifiedNamespace,
                    EventHubName            = EventHubName,
                    ConsumerGroup           = ConsumerGroup,
                    OwnerIdentifier         = OwnershipIdentifier,
                    PartitionId             = PartitionId,
                    LastModifiedTime        = DateTime.UtcNow,
                    Version = MatchingEtag
                }
            };

            var mockContainerClient = new MockBlobContainerClient().AddBlobClient($"{FullyQualifiedNamespace}/{EventHubName}/{ConsumerGroup}/ownership/1", client => client.BlobInfo = blobInfo);
            var target  = new BlobsCheckpointStore(mockContainerClient, DefaultRetryPolicy);
            var mockLog = new Mock <BlobEventStoreEventSource>();

            target.Logger = mockLog.Object;

            var result = await target.ClaimOwnershipAsync(partitionOwnership, CancellationToken.None);

            mockLog.Verify(m => m.OwnershipNotClaimable(PartitionId, FullyQualifiedNamespace, EventHubName, ConsumerGroup, OwnershipIdentifier, It.Is <string>(e => e.Contains(BlobErrorCode.ConditionNotMet.ToString()))));
        }
示例#5
0
        public EventHubListener(
            string functionId,
            ITriggeredFunctionExecutor executor,
            EventProcessorHost eventProcessorHost,
            bool singleDispatch,
            IEventHubConsumerClient consumerClient,
            BlobsCheckpointStore checkpointStore,
            EventHubOptions options,
            ILoggerFactory loggerFactory)
        {
            _loggerFactory      = loggerFactory;
            _executor           = executor;
            _eventProcessorHost = eventProcessorHost;
            _singleDispatch     = singleDispatch;
            _checkpointStore    = checkpointStore;
            _options            = options;
            _logger             = _loggerFactory.CreateLogger <EventHubListener>();

            _scaleMonitor = new Lazy <EventHubsScaleMonitor>(
                () => new EventHubsScaleMonitor(
                    functionId,
                    consumerClient,
                    checkpointStore,
                    _loggerFactory.CreateLogger <EventHubsScaleMonitor>()));

            _details = $"'namespace='{eventProcessorHost?.FullyQualifiedNamespace}', eventHub='{eventProcessorHost?.EventHubName}', " +
                       $"consumerGroup='{eventProcessorHost?.ConsumerGroup}', functionId='{functionId}', singleDispatch='{singleDispatch}'";
        }
示例#6
0
        public async Task CheckpointUpdateDoesNotInterfereWithOtherNamespaces()
        {
            await using (var storageScope = await StorageScope.CreateAsync())
            {
                var storageConnectionString = StorageTestEnvironment.StorageConnectionString;
                var containerClient         = new BlobContainerClient(storageConnectionString, storageScope.ContainerName);

                var checkpointStore = new BlobsCheckpointStore(containerClient);

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

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

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

                IEnumerable <Checkpoint> storedCheckpointsList2 = await checkpointStore.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));
            }
        }
示例#7
0
        public async Task OwnershipClaimFailsWhenETagExistsAndOwnershipDoesNotExist()
        {
            await using (StorageScope storageScope = await StorageScope.CreateAsync())
            {
                var storageConnectionString = StorageTestEnvironment.StorageConnectionString;
                var containerClient         = new BlobContainerClient(storageConnectionString, storageScope.ContainerName);

                var checkpointStore = new BlobsCheckpointStore(containerClient);
                var ownershipList   = new List <PartitionOwnership>();

                var eTaggyOwnership =
                    new PartitionOwnership
                    (
                        "namespace",
                        "eventHubName",
                        "consumerGroup",
                        "ownerIdentifier",
                        "partitionId",
                        eTag: "ETag"
                    );

                ownershipList.Add(eTaggyOwnership);

                await checkpointStore.ClaimOwnershipAsync(ownershipList);

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

                Assert.That(storedOwnershipList, Is.Not.Null.And.Empty);
            }
        }
示例#8
0
        public async Task GetCheckpointLogsInvalidCheckpoint()
        {
            var blobList = new List <BlobItem>
            {
                BlobsModelFactory.BlobItem($"{FullyQualifiedNamespace}/{EventHubName}/{ConsumerGroup}/checkpoint/0",
                                           false,
                                           BlobsModelFactory.BlobItemProperties(true, lastModified: DateTime.UtcNow, eTag: new ETag(MatchingEtag)),
                                           "snapshot",
                                           new Dictionary <string, string> {
                    { BlobMetadataKey.OwnerIdentifier, Guid.NewGuid().ToString() }
                })
            };
            var target = new BlobsCheckpointStore(new MockBlobContainerClient()
            {
                Blobs = blobList
            }, DefaultRetryPolicy);

            var mockLog = new Mock <BlobEventStoreEventSource>();

            target.Logger = mockLog.Object;

            await target.ListCheckpointsAsync(FullyQualifiedNamespace, EventHubName, ConsumerGroup, CancellationToken.None);

            mockLog.Verify(m => m.InvalidCheckpointFound("0", FullyQualifiedNamespace, EventHubName, ConsumerGroup));
        }
        public async Task OwnershipClaimSetsLastModifiedTimeAndETag()
        {
            await using (StorageScope storageScope = await StorageScope.CreateAsync())
            {
                var storageConnectionString = StorageTestEnvironment.StorageConnectionString;
                var containerClient         = new BlobContainerClient(storageConnectionString, storageScope.ContainerName);

                var checkpointStore = new BlobsCheckpointStore(containerClient, DefaultRetryPolicy);
                var ownershipList   = new List <PartitionOwnership>();
                var ownership       =
                    new PartitionOwnership
                    (
                        "namespace",
                        "eventHubName",
                        "consumerGroup",
                        "ownerIdentifier",
                        "partitionId"
                    );

                ownershipList.Add(ownership);

                await checkpointStore.ClaimOwnershipAsync(ownershipList, default);

                Assert.That(ownership.LastModifiedTime, Is.Not.Null);
                Assert.That(ownership.LastModifiedTime.Value, Is.GreaterThan(DateTimeOffset.UtcNow.Subtract(TimeSpan.FromSeconds(5))));

                Assert.That(ownership.ETag, Is.Not.Null);
            }
        }
        public async Task BlobStorageManagerCanClaimOwnership(string version)
        {
            await using (StorageScope storageScope = await StorageScope.CreateAsync())
            {
                var storageConnectionString = StorageTestEnvironment.StorageConnectionString;
                var containerClient = new BlobContainerClient(storageConnectionString, storageScope.ContainerName);

                var checkpointStore = new BlobsCheckpointStore(containerClient, DefaultRetryPolicy);
                var ownershipList = new List<EventProcessorPartitionOwnership>
                {
                    // Null version and non-null version hit different paths of the code, calling different methods that connect
                    // to the Storage service.

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

                Assert.That(async () => await checkpointStore.ClaimOwnershipAsync(ownershipList, default), Throws.Nothing);
            }
        }
        public async Task ListCheckpointsAsync_LogsOnInvalidCheckpoints()
        {
            var testLoggerProvider = new TestLoggerProvider();
            Mock <BlobContainerClient> containerClientMock = new Mock <BlobContainerClient>(MockBehavior.Strict);

            containerClientMock.Setup(c => c.GetBlobsAsync(It.IsAny <BlobTraits>(), It.IsAny <BlobStates>(), It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .Returns(AsyncPageable <BlobItem> .FromPages(new[]
            {
                Page <BlobItem> .FromValues(new[]
                {
                    BlobsModelFactory.BlobItem("testnamespace/testeventhubname/testconsumergroup/checkpoint/0", false, BlobsModelFactory.BlobItemProperties(false), metadata: new Dictionary <string, string>())
                }, null, Mock.Of <Response>())
            }));

            BlobsCheckpointStore store = new BlobsCheckpointStore(
                containerClientMock.Object,
                new BasicRetryPolicy(new EventHubsRetryOptions()),
                _functionId,
                testLoggerProvider.CreateLogger("TestLogger")
                );

            await store.ListCheckpointsAsync(_namespace, _eventHubName, _consumerGroup, CancellationToken.None);

            var warning         = testLoggerProvider.GetAllLogMessages().Single(p => p.Level == Extensions.Logging.LogLevel.Warning);
            var expectedWarning = "Function 'EventHubsTriggerFunction': An invalid checkpoint was found for partition: '0' of " +
                                  "FullyQualifiedNamespace: 'TestNamespace'; EventHubName: 'TestEventHubName'; ConsumerGroup: 'TestConsumerGroup'.  " +
                                  "This checkpoint is not valid and will be ignored.";

            Assert.AreEqual(expectedWarning, warning.FormattedMessage);
            testLoggerProvider.ClearAllLogMessages();
        }
        public async Task CheckReturnedEtagContainsSingleQuotes()
        {
            await using (StorageScope storageScope = await StorageScope.CreateAsync())
            {
                // A regular expression used to capture strings enclosed in double quotes.
                Regex s_doubleQuotesExpression = new Regex("\"(.*)\"", RegexOptions.Compiled);

                var storageConnectionString = StorageTestEnvironment.StorageConnectionString;
                var containerClient = new BlobContainerClient(storageConnectionString, storageScope.ContainerName);

                var checkpointStore = new BlobsCheckpointStore(containerClient, DefaultRetryPolicy);
                var ownershipList = new List<EventProcessorPartitionOwnership>();
                var ownership =
                    new EventProcessorPartitionOwnership
                    {
                        FullyQualifiedNamespace = "namespace",
                        EventHubName = "eventHubName",
                        ConsumerGroup = "consumerGroup",
                        OwnerIdentifier = "ownerIdentifier",
                        PartitionId = "partitionId"
                    };

                ownershipList.Add(ownership);

                IEnumerable<EventProcessorPartitionOwnership> claimedOwnership = await checkpointStore.ClaimOwnershipAsync(ownershipList, default);
                IEnumerable<EventProcessorPartitionOwnership> storedOwnershipList = await checkpointStore.ListOwnershipAsync("namespace", "eventHubName", "consumerGroup", default);

                var claimedOwnershipMatch = s_doubleQuotesExpression.Match(claimedOwnership.First().Version);
                var storedOwnershipListMatch = s_doubleQuotesExpression.Match(storedOwnershipList.First().Version);

                Assert.That(claimedOwnershipMatch.Success, Is.False);
                Assert.That(storedOwnershipListMatch.Success, Is.False);
            }
        }
示例#13
0
        public async Task CheckpointUpdateFailsWhenContainerDoesNotExist()
        {
            await using (StorageScope storageScope = await StorageScope.CreateAsync())
            {
                var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString;
                var containerClient         = new BlobContainerClient(storageConnectionString, $"test-container-{Guid.NewGuid()}");

                var checkpointStore = new BlobsCheckpointStore(containerClient, DefaultRetryPolicy);

                var checkpoint = new EventProcessorCheckpoint
                {
                    FullyQualifiedNamespace = "namespace",
                    EventHubName            = "eventHubName",
                    ConsumerGroup           = "consumerGroup",
                    PartitionId             = "partitionId"
                };

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

                Assert.That(async() => await checkpointStore.UpdateCheckpointAsync(checkpoint, mockEvent, default), Throws.InstanceOf <RequestFailedException>());
            }
        }
示例#14
0
        public async Task ClaimOwnershipLogsStartAndComplete()
        {
            var partitionOwnership = new List <EventProcessorPartitionOwnership>
            {
                new EventProcessorPartitionOwnership
                {
                    FullyQualifiedNamespace = FullyQualifiedNamespace,
                    EventHubName            = EventHubName,
                    ConsumerGroup           = ConsumerGroup,
                    OwnerIdentifier         = OwnershipIdentifier,
                    PartitionId             = PartitionId,
                    LastModifiedTime        = DateTime.UtcNow
                }
            };

            var mockBlobContainerClient = new MockBlobContainerClient().AddBlobClient($"{FullyQualifiedNamespace}/{EventHubName}/{ConsumerGroup}/ownership/1", _ => { });
            var target = new BlobsCheckpointStore(mockBlobContainerClient, DefaultRetryPolicy);

            var mockLog = new Mock <BlobEventStoreEventSource>();

            target.Logger = mockLog.Object;

            var result = await target.ClaimOwnershipAsync(partitionOwnership, CancellationToken.None);

            mockLog.Verify(m => m.ClaimOwnershipStart(PartitionId, FullyQualifiedNamespace, EventHubName, ConsumerGroup, OwnershipIdentifier));
            mockLog.Verify(m => m.ClaimOwnershipComplete(PartitionId, FullyQualifiedNamespace, EventHubName, ConsumerGroup, OwnershipIdentifier));
        }
        public async Task CheckpointUpdateDoesNotInterfereWithOtherPartitions()
        {
            await using (StorageScope storageScope = await StorageScope.CreateAsync())
            {
                var storageConnectionString = StorageTestEnvironment.StorageConnectionString;
                var containerClient         = new BlobContainerClient(storageConnectionString, storageScope.ContainerName);

                var checkpointStore = new BlobsCheckpointStore(containerClient, DefaultRetryPolicy);

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

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

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

                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);
            }
        }
        public async Task OwnershipClaimSetsLastModifiedTimeAndVersion()
        {
            await using (StorageScope storageScope = await StorageScope.CreateAsync())
            {
                var storageConnectionString = StorageTestEnvironment.StorageConnectionString;
                var containerClient = new BlobContainerClient(storageConnectionString, storageScope.ContainerName);

                var checkpointStore = new BlobsCheckpointStore(containerClient, DefaultRetryPolicy);
                var ownershipList = new List<EventProcessorPartitionOwnership>();
                var ownership =
                    new EventProcessorPartitionOwnership
                    {
                        FullyQualifiedNamespace = "namespace",
                        EventHubName = "eventHubName",
                        ConsumerGroup = "consumerGroup",
                        OwnerIdentifier = "ownerIdentifier",
                        PartitionId = "partitionId"
                    };

                ownershipList.Add(ownership);

                await checkpointStore.ClaimOwnershipAsync(ownershipList, default);

                Assert.That(ownership.LastModifiedTime, Is.Not.EqualTo(default(DateTimeOffset)));
                Assert.That(ownership.LastModifiedTime, Is.GreaterThan(DateTimeOffset.UtcNow.Subtract(TimeSpan.FromSeconds(5))));

                Assert.That(ownership.Version, Is.Not.Null);
            }
        }
        public async Task BlobPartitionManagerCanClaimOwnership(string eTag)
        {
            await using (StorageScope storageScope = await StorageScope.CreateAsync())
            {
                var storageConnectionString = StorageTestEnvironment.StorageConnectionString;
                var containerClient         = new BlobContainerClient(storageConnectionString, storageScope.ContainerName);

                var checkpointStore = new BlobsCheckpointStore(containerClient, DefaultRetryPolicy);
                var ownershipList   = new List <PartitionOwnership>
                {
                    // Null ETag and non-null ETag hit different paths of the code, calling different methods that connect
                    // to the Storage service.

                    new PartitionOwnership
                    (
                        "namespace",
                        "eventHubName",
                        "consumerGroup",
                        "ownerIdentifier",
                        "partitionId",
                        eTag: eTag
                    )
                };

                Assert.That(async() => await checkpointStore.ClaimOwnershipAsync(ownershipList, default), Throws.Nothing);
            }
        }
        public async Task BlobPartitionManagerCanUpdateCheckpoint()
        {
            await using (StorageScope storageScope = await StorageScope.CreateAsync())
            {
                var storageConnectionString = StorageTestEnvironment.StorageConnectionString;
                var containerClient         = new BlobContainerClient(storageConnectionString, storageScope.ContainerName);

                var checkpointStore = new BlobsCheckpointStore(containerClient, DefaultRetryPolicy);
                var ownershipList   = new List <PartitionOwnership>
                {
                    // Make sure the ownership exists beforehand so we hit all storage SDK calls in the checkpoint store.

                    new PartitionOwnership
                    (
                        "namespace",
                        "eventHubName",
                        "consumerGroup",
                        "ownerIdentifier",
                        "partitionId"
                    )
                };

                await checkpointStore.ClaimOwnershipAsync(ownershipList, default);

                var checkpoint = new Checkpoint("namespace", "eventHubName", "consumerGroup", "partitionId", 10, 20);

                Assert.That(async() => await checkpointStore.UpdateCheckpointAsync(checkpoint, default), Throws.Nothing);
            }
        }
        public async Task ListOwnershipLogsStartAndComplete()
        {
            var blobList = new List <BlobItem> {
                BlobsModelFactory.BlobItem($"{FullyQualifiedNamespace}/{EventHubName}/{ConsumerGroup}/ownership/{Guid.NewGuid().ToString()}",
                                           false,
                                           BlobsModelFactory.BlobItemProperties(true, lastModified: DateTime.UtcNow, eTag: new ETag(MatchingEtag)),
                                           "snapshot",
                                           new Dictionary <string, string> {
                    { BlobMetadataKey.OwnerIdentifier, Guid.NewGuid().ToString() }
                })
            };
            var target = new BlobsCheckpointStore(new MockBlobContainerClient()
            {
                Blobs = blobList
            },
                                                  new BasicRetryPolicy(new EventHubsRetryOptions()));
            var mockLog = new Mock <BlobEventStoreEventSource>();

            target.Logger = mockLog.Object;

            await target.ListOwnershipAsync(FullyQualifiedNamespace, EventHubName, ConsumerGroup, new CancellationToken());

            mockLog.Verify(m => m.ListOwnershipAsyncStart(FullyQualifiedNamespace, EventHubName, ConsumerGroup));
            mockLog.Verify(m => m.ListOwnershipAsyncComplete(FullyQualifiedNamespace, EventHubName, ConsumerGroup, blobList.Count));
        }
        public async Task OwnershipClaimFailsWhenVersionExistsAndOwnershipDoesNotExist()
        {
            await using (StorageScope storageScope = await StorageScope.CreateAsync())
            {
                var storageConnectionString = StorageTestEnvironment.StorageConnectionString;
                var containerClient = new BlobContainerClient(storageConnectionString, storageScope.ContainerName);

                var checkpointStore = new BlobsCheckpointStore(containerClient, DefaultRetryPolicy);
                var ownershipList = new List<EventProcessorPartitionOwnership>();

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

                ownershipList.Add(eTaggyOwnership);

                await checkpointStore.ClaimOwnershipAsync(ownershipList, default);

                IEnumerable<EventProcessorPartitionOwnership> storedOwnershipList = await checkpointStore.ListOwnershipAsync("namespace", "eventHubName", "consumerGroup", default);

                Assert.That(storedOwnershipList, Is.Not.Null.And.Empty);
            }
        }
        public async Task FirstOwnershipClaimSucceeds()
        {
            await using (StorageScope storageScope = await StorageScope.CreateAsync())
            {
                var storageConnectionString = StorageTestEnvironment.StorageConnectionString;
                var containerClient = new BlobContainerClient(storageConnectionString, storageScope.ContainerName);

                var checkpointStore = new BlobsCheckpointStore(containerClient, DefaultRetryPolicy);
                var ownershipList = new List<EventProcessorPartitionOwnership>();
                var ownership =
                    new EventProcessorPartitionOwnership
                    {
                        FullyQualifiedNamespace = "namespace",
                        EventHubName = "eventHubName",
                        ConsumerGroup = "consumerGroup",
                        OwnerIdentifier = "ownerIdentifier",
                        PartitionId = "partitionId"
                    };

                ownershipList.Add(ownership);

                await checkpointStore.ClaimOwnershipAsync(ownershipList, default);

                IEnumerable<EventProcessorPartitionOwnership> storedOwnershipList = await checkpointStore.ListOwnershipAsync("namespace", "eventHubName", "consumerGroup", default);

                Assert.That(storedOwnershipList, Is.Not.Null);
                Assert.That(storedOwnershipList.Count, Is.EqualTo(1));
                Assert.That(storedOwnershipList.Single().IsEquivalentTo(ownership), Is.True);
            }
        }
 public Processor(int eventBatchMaximumCount, string consumerGroup, string connectionString, string eventHubName, EventProcessorOptions options, IEventProcessorFactory processorFactory, bool invokeProcessorAfterRecieveTimeout, Action <ExceptionReceivedEventArgs> exceptionHandler, BlobsCheckpointStore checkpointStore) : base(eventBatchMaximumCount, consumerGroup, connectionString, eventHubName, options)
 {
     ProcessorFactory = processorFactory;
     InvokeProcessorAfterRecieveTimeout = invokeProcessorAfterRecieveTimeout;
     ExceptionHandler = exceptionHandler;
     LeaseInfos       = new ConcurrentDictionary <string, LeaseInfo>();
     CheckpointStore  = checkpointStore;
 }
示例#23
0
 public async Task StartProcessingAsync(
     IEventProcessorFactory processorFactory,
     BlobsCheckpointStore checkpointStore,
     CancellationToken cancellationToken)
 {
     _processorFactory = processorFactory;
     _checkpointStore  = checkpointStore;
     await StartProcessingAsync(cancellationToken).ConfigureAwait(false);
 }
        public Task <ITriggerBinding> TryCreateAsync(TriggerBindingProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            ParameterInfo            parameter = context.Parameter;
            EventHubTriggerAttribute attribute = parameter.GetCustomAttribute <EventHubTriggerAttribute>(inherit: false);

            if (attribute == null)
            {
                return(Task.FromResult <ITriggerBinding>(null));
            }

            string resolvedEventHubName = _nameResolver.ResolveWholeString(attribute.EventHubName);

            string consumerGroup         = attribute.ConsumerGroup ?? EventHubConsumerClient.DefaultConsumerGroupName;
            string resolvedConsumerGroup = _nameResolver.ResolveWholeString(consumerGroup);

            if (!string.IsNullOrWhiteSpace(attribute.Connection))
            {
                var connection       = _nameResolver.ResolveWholeString(attribute.Connection);
                var connectionString = _config.GetConnectionStringOrSetting(connection);
                _options.Value.AddReceiver(resolvedEventHubName, connectionString);
            }

            var eventHostListener = _options.Value.GetEventProcessorHost(resolvedEventHubName, resolvedConsumerGroup);
            var checkpointStoreConnectionString = _options.Value.GetCheckpointStoreConnectionString(_config, resolvedEventHubName);

            Func <ListenerFactoryContext, bool, Task <IListener> > createListener =
                (factoryContext, singleDispatch) =>
            {
                var checkpointStore = new BlobsCheckpointStore(
                    new BlobContainerClient(checkpointStoreConnectionString, _options.Value.LeaseContainerName),
                    _options.Value.EventProcessorOptions.RetryOptions.ToRetryPolicy(),
                    factoryContext.Descriptor.Id,
                    _logger);

                IListener listener = new EventHubListener(
                    factoryContext.Descriptor.Id,
                    factoryContext.Executor,
                    eventHostListener,
                    singleDispatch,
                    () => _options.Value.GetEventHubConsumerClient(resolvedEventHubName, consumerGroup),
                    checkpointStore,
                    _options.Value,
                    _logger);
                return(Task.FromResult(listener));
            };

#pragma warning disable 618
            ITriggerBinding binding = BindingFactory.GetTriggerBinding(new EventHubTriggerBindingStrategy(), parameter, _converterManager, createListener);
#pragma warning restore 618
            return(Task.FromResult(binding));
        }
示例#25
0
        public void ListOwnershipLogsErrorOnException()
        {
            var ex     = new RequestFailedException(0, "foo", BlobErrorCode.ContainerNotFound.ToString(), null);
            var target = new BlobsCheckpointStore(new MockBlobContainerClient(getBlobsAsyncException: ex),
                                                  DefaultRetryPolicy);
            var mockLog = new Mock <BlobEventStoreEventSource>();

            target.Logger = mockLog.Object;

            Assert.That(async() => await target.ListOwnershipAsync(FullyQualifiedNamespace, EventHubName, ConsumerGroup, CancellationToken.None), Throws.InstanceOf <RequestFailedException>());
            mockLog.Verify(m => m.ListOwnershipError(FullyQualifiedNamespace, EventHubName, ConsumerGroup, ex.Message));
        }
        public async Task ListCheckpointsFailsWhenContainerDoesNotExist()
        {
            await using (StorageScope storageScope = await StorageScope.CreateAsync())
            {
                var storageConnectionString = StorageTestEnvironment.StorageConnectionString;
                var containerClient = new BlobContainerClient(storageConnectionString, $"test-container-{Guid.NewGuid()}");

                var checkpointStore = new BlobsCheckpointStore(containerClient, DefaultRetryPolicy);

                Assert.That(async () => await checkpointStore.ListCheckpointsAsync("namespace", "eventHubName", "consumerGroup", default), Throws.InstanceOf<RequestFailedException>());
            }
        }
        public async Task BlobStorageManagerCanListCheckpoints()
        {
            await using (StorageScope storageScope = await StorageScope.CreateAsync())
            {
                var storageConnectionString = StorageTestEnvironment.StorageConnectionString;
                var containerClient = new BlobContainerClient(storageConnectionString, storageScope.ContainerName);

                var checkpointStore = new BlobsCheckpointStore(containerClient, DefaultRetryPolicy);

                Assert.That(async () => await checkpointStore.ListCheckpointsAsync("namespace", "eventHubName", "consumerGroup", default), Throws.Nothing);
            }
        }
        public void ListCheckointsForMissingPartitionThrowsAndLogsOwnershipNotClaimable()
        {
            var ex = new RequestFailedException(0, "foo", BlobErrorCode.ContainerNotFound.ToString(), null);

            var target = new BlobsCheckpointStore(new MockBlobContainerClient(getBlobsAsyncException: ex),
                                                  new BasicRetryPolicy(new EventHubsRetryOptions()));
            var mockLog = new Mock <BlobEventStoreEventSource>();

            target.Logger = mockLog.Object;

            Assert.ThrowsAsync <RequestFailedException>(async() => await target.ListCheckpointsAsync(FullyQualifiedNamespace, EventHubName, ConsumerGroup, new CancellationToken()));
        }
示例#29
0
        public async Task BlobPartitionManagerCanListOwnership()
        {
            await using (StorageScope storageScope = await StorageScope.CreateAsync())
            {
                var storageConnectionString = StorageTestEnvironment.StorageConnectionString;
                var containerClient         = new BlobContainerClient(storageConnectionString, storageScope.ContainerName);

                var checkpointStore = new BlobsCheckpointStore(containerClient);

                Assert.That(async() => await checkpointStore.ListOwnershipAsync("namespace", "eventHubName", "consumerGroup"), Throws.Nothing);
            }
        }
        public async Task ListCheckpointAsyncReturnsEmptyIEnumerableWhenThereAreNoCheckpoints()
        {
            await using (StorageScope storageScope = await StorageScope.CreateAsync())
            {
                var storageConnectionString = StorageTestEnvironment.StorageConnectionString;
                var containerClient = new BlobContainerClient(storageConnectionString, storageScope.ContainerName);

                var checkpointStore = new BlobsCheckpointStore(containerClient, DefaultRetryPolicy);
                IEnumerable<EventProcessorCheckpoint> checkpoints = await checkpointStore.ListCheckpointsAsync("namespace", "eventHubName", "consumerGroup", default);

                Assert.That(checkpoints, Is.Not.Null.And.Empty);
            }
        }