public void ConnectionConstructorCreatesDefaultOptions()
        {
            var expected = new EventHubProducerClientOptions().RetryOptions;
            var mockConnection = new MockConnection();
            var producer = new EventHubProducerClient(mockConnection);

            var policy = GetRetryPolicy(producer);
            Assert.That(policy, Is.Not.Null, "There should have been a retry policy set.");
            Assert.That(policy, Is.InstanceOf<BasicRetryPolicy>(), "The default retry policy should be a basic policy.");

            var actual = ((BasicRetryPolicy)policy).Options;
            Assert.That(actual.IsEquivalentTo(expected), Is.True, "The default retry policy should be based on the default retry options.");
        }
예제 #2
0
        public void ConnectionConstructorSetsTheRetryPolicy()
        {
            var expected = Mock.Of <EventHubsRetryPolicy>();
            var options  = new EventHubProducerClientOptions {
                RetryOptions = new RetryOptions {
                    CustomRetryPolicy = expected
                }
            };
            var mockConnection = new MockConnection();
            var producer       = new EventHubProducerClient(mockConnection, options);

            Assert.That(GetRetryPolicy(producer), Is.SameAs(expected));
        }
예제 #3
0
        public async Task GetPartitionPropertiesUsesTheRetryPolicy()
        {
            var mockConnection = new MockConnection();
            var retryPolicy    = Mock.Of <EventHubsRetryPolicy>();
            var options        = new EventHubProducerClientOptions {
                RetryOptions = new RetryOptions {
                    CustomRetryPolicy = retryPolicy
                }
            };
            var producer = new EventHubProducerClient(mockConnection, options);

            await producer.GetPartitionPropertiesAsync("1");

            Assert.That(mockConnection.GetPartitionPropertiesInvokedWith, Is.SameAs(retryPolicy), "Either the call was not delegated or the retry policy was not passed.");
        }
        public async Task CloseSurfacesExceptionsForTransportConsumers()
        {
            var mockTransportProducer = new Mock<TransportProducer>();
            var mockConnection = new MockConnection(() => mockTransportProducer.Object);
            var mockBatch = new EventDataBatch(new MockTransportBatch(), new SendOptions { PartitionId = "1" });;
            var producer = new EventHubProducerClient(mockConnection);

            mockTransportProducer
                .Setup(producer => producer.CloseAsync(It.IsAny<CancellationToken>()))
                .Returns(Task.FromException(new InvalidCastException()));

            try { await producer.SendAsync(mockBatch); } catch {}

            Assert.That(() => producer.Close(), Throws.InstanceOf<Exception>());
        }
예제 #5
0
        public async Task EventHubProducerCreatesDiagnosticScopeOnBatchSend()
        {
            using var testListener = new ClientDiagnosticListener(DiagnosticSourceName);

            var eventHubName       = "SomeName";
            var endpoint           = new Uri("amqp://endpoint");
            var fakeConnection     = new MockConnection(endpoint, eventHubName);
            var eventCount         = 0;
            var batchTransportMock = new Mock <TransportEventBatch>();

            batchTransportMock
            .Setup(m => m.TryAdd(It.IsAny <EventData>()))
            .Returns(() =>
            {
                eventCount++;
                return(eventCount <= 3);
            });

            var transportMock = new Mock <TransportProducer>();

            transportMock
            .Setup(m => m.SendAsync(It.IsAny <IEnumerable <EventData> >(), It.IsAny <SendEventOptions>(), It.IsAny <CancellationToken>()))
            .Returns(Task.CompletedTask);

            transportMock
            .Setup(m => m.CreateBatchAsync(It.IsAny <CreateBatchOptions>(), It.IsAny <CancellationToken>()))
            .Returns(new ValueTask <TransportEventBatch>(Task.FromResult(batchTransportMock.Object)));

            var producer = new EventHubProducerClient(fakeConnection, transportMock.Object);

            var            eventData = new EventData(ReadOnlyMemory <byte> .Empty);
            EventDataBatch batch     = await producer.CreateBatchAsync();

            Assert.True(batch.TryAdd(eventData));

            await producer.SendAsync(batch);

            ClientDiagnosticListener.ProducedDiagnosticScope sendScope = testListener.AssertScope(DiagnosticProperty.ProducerActivityName,
                                                                                                  new KeyValuePair <string, string>(DiagnosticProperty.TypeAttribute, DiagnosticProperty.EventHubProducerType),
                                                                                                  new KeyValuePair <string, string>(DiagnosticProperty.ServiceContextAttribute, DiagnosticProperty.EventHubsServiceContext),
                                                                                                  new KeyValuePair <string, string>(DiagnosticProperty.EventHubAttribute, eventHubName),
                                                                                                  new KeyValuePair <string, string>(DiagnosticProperty.EndpointAttribute, endpoint.ToString()));

            ClientDiagnosticListener.ProducedDiagnosticScope messageScope = testListener.AssertScope(DiagnosticProperty.EventActivityName);

            Assert.That(eventData.Properties[DiagnosticProperty.DiagnosticIdAttribute], Is.EqualTo(messageScope.Activity.Id), "The diagnostics identifier should match.");
            Assert.That(messageScope.Activity, Is.Not.SameAs(sendScope.Activity), "The activities should not be the same instance.");
        }
        public void TransportProducerPoolAllowsTakingTheRightTransportProducer(string partitionId)
        {
            var transportProducer = new ObservableTransportProducerMock();
            var partitionProducer = new ObservableTransportProducerMock(partitionId);
            var connection        = new MockConnection(() => partitionProducer);
            var retryPolicy       = new EventHubProducerClientOptions().RetryOptions.ToRetryPolicy();
            var startingPool      = new ConcurrentDictionary <string, TransportProducerPool.PoolItem>
            {
                ["0"] = new TransportProducerPool.PoolItem("0", partitionProducer)
            };
            TransportProducerPool transportProducerPool = new TransportProducerPool(connection, retryPolicy, eventHubProducer: transportProducer);

            var returnedProducer = transportProducerPool.GetPooledProducer(partitionId).TransportProducer as ObservableTransportProducerMock;

            Assert.That(returnedProducer.PartitionId, Is.EqualTo(partitionId));
        }
예제 #7
0
        public async Task CheckpointManagerCreatesScope()
        {
            using ClientDiagnosticListener listener = new ClientDiagnosticListener(DiagnosticSourceName);

            var eventHubName   = "SomeName";
            var endpoint       = new Uri("amqp://some.endpoint.com/path");
            var fakeConnection = new MockConnection(endpoint, eventHubName);
            var context        = new PartitionContext(eventHubName, "partition");
            var data           = new EventData(new byte[0], sequenceNumber: 0, offset: 0);

            var processor = new EventProcessorClient("cg", new InMemoryPartitionManager(), fakeConnection, null);

            await processor.UpdateCheckpointAsync(data, context);

            ClientDiagnosticListener.ProducedDiagnosticScope scope = listener.Scopes.Single();
            Assert.That(scope.Name, Is.EqualTo(DiagnosticProperty.EventProcessorCheckpointActivityName));
        }
        public async Task PoolItemsAreRefreshedOnDisposal()
        {
            var transportProducer = new ObservableTransportProducerMock();
            var startingPool      = new ConcurrentDictionary <string, TransportProducerPool.PoolItem>
            {
                ["0"] = new TransportProducerPool.PoolItem("0", transportProducer)
            };
            var connection  = new MockConnection(() => transportProducer);
            var retryPolicy = new EventHubProducerClientOptions().RetryOptions.ToRetryPolicy();
            TransportProducerPool transportProducerPool = new TransportProducerPool(connection, retryPolicy);
            var expectedTime = DateTimeOffset.UtcNow.AddMinutes(10);

            await using var pooledProducer = transportProducerPool.GetPooledProducer("0");

            // This call should refresh the timespan associated to an item in the pool
            await pooledProducer.DisposeAsync();

            Assert.That(startingPool["0"].RemoveAfter, Is.InRange(expectedTime.AddMinutes(-1), expectedTime.AddMinutes(1)), $"The remove after of a pool item should be extended.");
        }
        public void CloseAsyncSurfacesExceptionsForPartitionTransportProducer()
        {
            var transportProducer = new Mock <TransportProducer>();
            var partitionProducer = new Mock <TransportProducer>();
            var connection        = new MockConnection(() => partitionProducer.Object);
            var retryPolicy       = new EventHubProducerClientOptions().RetryOptions.ToRetryPolicy();
            var startingPool      = new ConcurrentDictionary <string, TransportProducerPool.PoolItem>
            {
                ["0"] = new TransportProducerPool.PoolItem("0", partitionProducer.Object)
            };
            TransportProducerPool transportProducerPool = new TransportProducerPool(connection, retryPolicy, eventHubProducer: transportProducer.Object);

            partitionProducer
            .Setup(producer => producer.CloseAsync(It.IsAny <CancellationToken>()))
            .Returns(Task.FromException(new InvalidCastException()));

            var _ = transportProducerPool.GetPooledProducer("0");

            Assert.That(async() => await transportProducerPool.CloseAsync(), Throws.InstanceOf <InvalidCastException>());
        }
        public void TransportProducerPoolRefreshesAccessedItems()
        {
            DateTimeOffset oneMinuteAgo      = DateTimeOffset.UtcNow.Subtract(TimeSpan.FromMinutes(1));
            var            transportProducer = new ObservableTransportProducerMock();
            var            connection        = new MockConnection(() => transportProducer);
            var            retryPolicy       = new EventHubProducerClientOptions().RetryOptions.ToRetryPolicy();
            var            startingPool      = new ConcurrentDictionary <string, TransportProducerPool.PoolItem>
            {
                // An expired item in the pool
                ["0"] = new TransportProducerPool.PoolItem("0", transportProducer, removeAfter: oneMinuteAgo)
            };
            TransportProducerPool transportProducerPool = new TransportProducerPool(connection, retryPolicy, startingPool);

            // This call should refresh the timespan associated to the item
            _ = transportProducerPool.GetPooledProducer("0");

            // The expiration call back should not remove the item
            GetExpirationCallBack(transportProducerPool).Invoke(null);

            Assert.That(startingPool.TryGetValue("0", out _), Is.True, "The item in the pool should be refreshed and not have been removed.");
        }
        public async Task TransportProducerPoolAllowsConfiguringRemoveAfter()
        {
            var transportProducer = new ObservableTransportProducerMock();
            var connection        = new MockConnection(() => transportProducer);
            var retryPolicy       = new EventHubProducerClientOptions().RetryOptions.ToRetryPolicy();
            var startingPool      = new ConcurrentDictionary <string, TransportProducerPool.PoolItem>
            {
                ["0"] = new TransportProducerPool.PoolItem("0", transportProducer)
            };
            TransportProducerPool transportProducerPool = new TransportProducerPool(connection, retryPolicy, startingPool);

            var pooledProducer = transportProducerPool.GetPooledProducer("0", TimeSpan.FromMinutes(-1));

            await using (var _ = pooledProducer.ConfigureAwait(false))
            {
            };

            GetExpirationCallBack(transportProducerPool).Invoke(null);

            Assert.That(transportProducer.CloseCallCount, Is.EqualTo(1));
        }
        public void TransportProducerPoolRemovesExpiredItems()
        {
            var            transportProducer = new ObservableTransportProducerMock();
            var            connection        = new MockConnection(() => transportProducer);
            var            retryPolicy       = new EventHubProducerClientOptions().RetryOptions.ToRetryPolicy();
            DateTimeOffset oneMinuteAgo      = DateTimeOffset.UtcNow.Subtract(TimeSpan.FromMinutes(1));
            var            startingPool      = new ConcurrentDictionary <string, TransportProducerPool.PoolItem>
            {
                // An expired item in the pool
                ["0"] = new TransportProducerPool.PoolItem("0", transportProducer, removeAfter: oneMinuteAgo),
                ["1"] = new TransportProducerPool.PoolItem("0", transportProducer),
                ["2"] = new TransportProducerPool.PoolItem("0", transportProducer),
            };
            TransportProducerPool transportProducerPool = new TransportProducerPool(connection, retryPolicy, startingPool);

            GetExpirationCallBack(transportProducerPool).Invoke(null);

            Assert.That(startingPool.TryGetValue("0", out _), Is.False, "PerformExpiration should remove an expired producer from the pool.");
            Assert.That(transportProducer.CloseCallCount, Is.EqualTo(1), "PerformExpiration should close an expired producer.");
            Assert.That(startingPool.TryGetValue("1", out _), Is.True, "PerformExpiration should not remove valid producers.");
            Assert.That(startingPool.TryGetValue("2", out _), Is.True, "PerformExpiration should not remove valid producers.");
        }
예제 #13
0
        public async Task EventHubProducerCreatesDiagnosticScopeOnSend()
        {
            using var testListener = new ClientDiagnosticListener(DiagnosticSourceName);
            var activity = new Activity("SomeActivity").Start();

            var eventHubName   = "SomeName";
            var endpoint       = "endpoint";
            var fakeConnection = new MockConnection(endpoint, eventHubName);
            var transportMock  = new Mock <TransportProducer>();

            transportMock
            .Setup(m => m.SendAsync(It.IsAny <IEnumerable <EventData> >(), It.IsAny <SendEventOptions>(), It.IsAny <CancellationToken>()))
            .Returns(Task.CompletedTask);

            var producer = new EventHubProducerClient(fakeConnection, transportMock.Object);

            var eventData = new EventData(ReadOnlyMemory <byte> .Empty);
            await producer.SendAsync(eventData);

            activity.Stop();

            ClientDiagnosticListener.ProducedDiagnosticScope sendScope = testListener.AssertScope(DiagnosticProperty.ProducerActivityName,
                                                                                                  new KeyValuePair <string, string>(DiagnosticProperty.KindAttribute, DiagnosticProperty.ClientKind),
                                                                                                  new KeyValuePair <string, string>(DiagnosticProperty.ServiceContextAttribute, DiagnosticProperty.EventHubsServiceContext),
                                                                                                  new KeyValuePair <string, string>(DiagnosticProperty.EventHubAttribute, eventHubName),
                                                                                                  new KeyValuePair <string, string>(DiagnosticProperty.EndpointAttribute, endpoint));

            ClientDiagnosticListener.ProducedDiagnosticScope messageScope = testListener.AssertScope(DiagnosticProperty.EventActivityName,
                                                                                                     new KeyValuePair <string, string>(DiagnosticProperty.EventHubAttribute, eventHubName),
                                                                                                     new KeyValuePair <string, string>(DiagnosticProperty.EndpointAttribute, endpoint));

            Assert.That(eventData.Properties[DiagnosticProperty.DiagnosticIdAttribute], Is.EqualTo(messageScope.Activity.Id), "The diagnostics identifier should match.");
            Assert.That(messageScope.Activity.Tags, Has.One.EqualTo(new KeyValuePair <string, string>(DiagnosticProperty.KindAttribute, DiagnosticProperty.ProducerKind)), "The activities tag should be internal.");
            Assert.That(messageScope.Activity, Is.Not.SameAs(sendScope.Activity), "The activities should not be the same instance.");
            Assert.That(sendScope.Activity.ParentId, Is.EqualTo(activity.Id), "The send scope's parent identifier should match the activity in the active scope.");
            Assert.That(messageScope.Activity.ParentId, Is.EqualTo(activity.Id), "The message scope's parent identifier should match the activity in the active scope.");
        }
        public async Task TransportProducerPoolTracksAProducerUsage()
        {
            DateTimeOffset oneMinuteAgo      = DateTimeOffset.UtcNow.Subtract(TimeSpan.FromMinutes(1));
            var            transportProducer = new ObservableTransportProducerMock();
            var            connection        = new MockConnection(() => transportProducer);
            var            retryPolicy       = new EventHubProducerClientOptions().RetryOptions.ToRetryPolicy();
            var            startingPool      = new ConcurrentDictionary <string, TransportProducerPool.PoolItem>
            {
                // An expired item in the pool
                ["0"] = new TransportProducerPool.PoolItem("0", transportProducer, removeAfter: oneMinuteAgo)
            };
            TransportProducerPool transportProducerPool = new TransportProducerPool(connection, retryPolicy, startingPool);

            var pooledProducer = transportProducerPool.GetPooledProducer("0");

            startingPool.TryGetValue("0", out var poolItem);

            await using (pooledProducer)
            {
                Assert.That(poolItem.ActiveInstances.Count, Is.EqualTo(1), "The usage of a transport producer should be tracked.");
            }

            Assert.That(poolItem.ActiveInstances.Count, Is.EqualTo(0), "After usage an active instance should be removed from the pool.");
        }
        public async Task EventHubProducerCreatesDiagnosticScopeOnBatchSend()
        {
            using var testListener = new ClientDiagnosticListener(EventDataInstrumentation.DiagnosticNamespace);
            var activity = new Activity("SomeActivity").Start();

            var eventCount         = 0;
            var eventHubName       = "SomeName";
            var endpoint           = "endpoint";
            var batchEvent         = default(EventData);
            var fakeConnection     = new MockConnection(endpoint, eventHubName);
            var batchTransportMock = new Mock <TransportEventBatch>();

            batchTransportMock
            .Setup(m => m.TryAdd(It.IsAny <EventData>()))
            .Callback <EventData>(addedEvent => batchEvent = addedEvent)
            .Returns(() =>
            {
                eventCount++;
                return(eventCount <= 1);
            });

            batchTransportMock
            .Setup(m => m.Count)
            .Returns(1);

            var transportMock = new Mock <TransportProducer>();

            transportMock
            .Setup(m => m.SendAsync(It.IsAny <IEnumerable <EventData> >(), It.IsAny <SendEventOptions>(), It.IsAny <CancellationToken>()))
            .Returns(Task.CompletedTask);

            transportMock
            .Setup(m => m.CreateBatchAsync(It.IsAny <CreateBatchOptions>(), It.IsAny <CancellationToken>()))
            .Returns(new ValueTask <TransportEventBatch>(Task.FromResult(batchTransportMock.Object)));

            var producer = new EventHubProducerClient(fakeConnection, transportMock.Object);

            var eventData = new EventData(ReadOnlyMemory <byte> .Empty);
            var batch     = await producer.CreateBatchAsync();

            Assert.That(batch.TryAdd(eventData), Is.True);

            await producer.SendAsync(batch);

            activity.Stop();

            ClientDiagnosticListener.ProducedDiagnosticScope sendScope = testListener.AssertScope(DiagnosticProperty.ProducerActivityName,
                                                                                                  new KeyValuePair <string, string>(DiagnosticProperty.KindAttribute, DiagnosticProperty.ClientKind),
                                                                                                  new KeyValuePair <string, string>(DiagnosticProperty.ServiceContextAttribute, DiagnosticProperty.EventHubsServiceContext),
                                                                                                  new KeyValuePair <string, string>(DiagnosticProperty.EventHubAttribute, eventHubName),
                                                                                                  new KeyValuePair <string, string>(DiagnosticProperty.EndpointAttribute, endpoint));

            ClientDiagnosticListener.ProducedDiagnosticScope messageScope = testListener.AssertScope(DiagnosticProperty.EventActivityName,
                                                                                                     new KeyValuePair <string, string>(DiagnosticProperty.EventHubAttribute, eventHubName),
                                                                                                     new KeyValuePair <string, string>(DiagnosticProperty.EndpointAttribute, endpoint));

            Assert.That(batchEvent.Properties[DiagnosticProperty.DiagnosticIdAttribute], Is.EqualTo(messageScope.Activity.Id), "The diagnostics identifier should match.");
            Assert.That(messageScope.Activity, Is.Not.SameAs(sendScope.Activity), "The activities should not be the same instance.");
            Assert.That(sendScope.Activity.ParentId, Is.EqualTo(activity.Id), "The send scope's parent identifier should match the activity in the active scope.");
            Assert.That(messageScope.Activity.ParentId, Is.EqualTo(activity.Id), "The message scope's parent identifier should match the activity in the active scope.");
        }