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."); }
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)); }
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>()); }
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)); }
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."); }
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."); }