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(partition => connection.CreateTransportProducer(partition, TransportProducerFeatures.None, null, 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 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(partition => connection.CreateTransportProducer(partition, TransportProducerFeatures.None, null, 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 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(partition => connection.CreateTransportProducer(partition, TransportProducerFeatures.None, null, 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 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(partition => connection.CreateTransportProducer(partition, TransportProducerFeatures.None, null, 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 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(partition => connection.CreateTransportProducer(partition, TransportProducerFeatures.None, null, retryPolicy), eventHubProducer: transportProducer); var returnedProducer = transportProducerPool.GetPooledProducer(partitionId).TransportProducer as ObservableTransportProducerMock; Assert.That(returnedProducer.PartitionId, Is.EqualTo(partitionId)); }
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(partition => connection.CreateTransportProducer(partition, TransportProducerFeatures.None, null, 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 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(partition => connection.CreateTransportProducer(partition, TransportProducerFeatures.None, null, 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."); }