diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/src/Amqp/AmqpConnectionScope.cs b/sdk/eventhub/Azure.Messaging.EventHubs/src/Amqp/AmqpConnectionScope.cs index 8fd0d57aa14f..af0925545893 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/src/Amqp/AmqpConnectionScope.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/src/Amqp/AmqpConnectionScope.cs @@ -76,6 +76,18 @@ internal class AmqpConnectionScope : IDisposable /// private static TimeSpan MinimumAuthorizationRefresh { get; } = TimeSpan.FromMinutes(2); + /// + /// The maximum amount of time to allow before authorization is refreshed; any calculations + /// that call for refreshing less frequently will be substituted with this value. + /// + /// + /// + /// This value must be less than 49 days, 17 hours, 2 minutes, 47 seconds, 294 milliseconds + /// in order to not overflow the Timer used to track authorization refresh. + /// + /// + private static TimeSpan MaximumAuthorizationRefresh { get; } = TimeSpan.FromDays(49); + /// /// The amount time to allow to refresh authorization of an AMQP link. /// @@ -758,7 +770,13 @@ protected virtual TimeSpan CalculateLinkAuthorizationRefreshInterval(DateTime ex currentTimeUtc ??= DateTime.UtcNow; var refreshDueInterval = (expirationTimeUtc.Subtract(AuthorizationRefreshBuffer)).Subtract(currentTimeUtc.Value); - return (refreshDueInterval < MinimumAuthorizationRefresh) ? MinimumAuthorizationRefresh : refreshDueInterval; + + return refreshDueInterval switch + { + _ when (refreshDueInterval < MinimumAuthorizationRefresh) => MinimumAuthorizationRefresh, + _ when (refreshDueInterval > MaximumAuthorizationRefresh) => MaximumAuthorizationRefresh, + _ => refreshDueInterval + }; } /// diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Amqp/AmqpConnectionScopeTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Amqp/AmqpConnectionScopeTests.cs index 57fcb88e564c..2abbdeabe86c 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Amqp/AmqpConnectionScopeTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Amqp/AmqpConnectionScopeTests.cs @@ -2003,6 +2003,45 @@ public void CalculateLinkAuthorizationRefreshIntervalRespectsTheRefreshBuffer() Assert.That(calculatedExpire, Is.EqualTo(expireTime.Subtract(buffer)).Within(TimeSpan.FromSeconds(2)), "The authorization buffer should have been used for buffering."); } + /// + /// Verifies functionality of the + /// method. + /// + /// + [Test] + public void CalculateLinkAuthorizationRefreshIntervalRespectsTheMinimumDuration() + { + var endPoint = new Uri("sb://mine.hubs.com"); + var credential = new Mock(Mock.Of(), "{namespace}.servicebus.windows.net"); + var mockScope = new MockConnectionMockScope(endPoint, endPoint, "test", credential.Object, EventHubsTransportType.AmqpTcp, null); + var currentTime = new DateTime(2015, 10, 27, 00, 00, 00); + var minimumRefresh = GetMinimumAuthorizationRefresh(); + var expireTime = currentTime.Add(minimumRefresh.Subtract(TimeSpan.FromMilliseconds(500))); + var calculatedRefresh = mockScope.InvokeCalculateLinkAuthorizationRefreshInterval(expireTime, currentTime); + + Assert.That(calculatedRefresh, Is.EqualTo(minimumRefresh), "The minimum refresh duration should have been used."); + } + + /// + /// Verifies functionality of the + /// method. + /// + /// + [Test] + public void CalculateLinkAuthorizationRefreshIntervalRespectsTheMaximumDuration() + { + var endPoint = new Uri("sb://mine.hubs.com"); + var credential = new Mock(Mock.Of(), "{namespace}.servicebus.windows.net"); + var mockScope = new MockConnectionMockScope(endPoint, endPoint, "test", credential.Object, EventHubsTransportType.AmqpTcp, null); + var currentTime = new DateTime(2015, 10, 27, 00, 00, 00); + var refreshBuffer = GetAuthorizationRefreshBuffer(); + var maximumRefresh = GetMaximumAuthorizationRefresh(); + var expireTime = currentTime.Add(maximumRefresh.Add(refreshBuffer).Add(TimeSpan.FromMilliseconds(500))); + var calculatedRefresh = mockScope.InvokeCalculateLinkAuthorizationRefreshInterval(expireTime, currentTime); + + Assert.That(calculatedRefresh, Is.EqualTo(maximumRefresh), "The maximum refresh duration should have been used."); + } + /// /// Gets the active connection for the given scope, using the /// private property accessor. @@ -2047,6 +2086,28 @@ private static TimeSpan GetAuthorizationRefreshBuffer() => .GetProperty("AuthorizationRefreshBuffer", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.GetProperty) .GetValue(null); + /// + /// Gets the minimum authorization refresh interval, using the + /// private property accessor. + /// + /// + private static TimeSpan GetMinimumAuthorizationRefresh() => + (TimeSpan) + typeof(AmqpConnectionScope) + .GetProperty("MinimumAuthorizationRefresh", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.GetProperty) + .GetValue(null); + + /// + /// Gets the maximum authorization refresh interval, using the + /// private property accessor. + /// + /// + private static TimeSpan GetMaximumAuthorizationRefresh() => + (TimeSpan) + typeof(AmqpConnectionScope) + .GetProperty("MaximumAuthorizationRefresh", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.GetProperty) + .GetValue(null); + /// /// Creates a set of dummy settings for testing purposes. /// diff --git a/sdk/servicebus/Azure.Messaging.ServiceBus/src/Amqp/AmqpConnectionScope.cs b/sdk/servicebus/Azure.Messaging.ServiceBus/src/Amqp/AmqpConnectionScope.cs index bab7c93de223..c6dab02cffdd 100644 --- a/sdk/servicebus/Azure.Messaging.ServiceBus/src/Amqp/AmqpConnectionScope.cs +++ b/sdk/servicebus/Azure.Messaging.ServiceBus/src/Amqp/AmqpConnectionScope.cs @@ -61,6 +61,18 @@ internal class AmqpConnectionScope : TransportConnectionScope /// private static TimeSpan MinimumAuthorizationRefresh { get; } = TimeSpan.FromMinutes(2); + /// + /// The maximum amount of time to allow before authorization is refreshed; any calculations + /// that call for refreshing less frequently will be substituted with this value. + /// + /// + /// + /// This value must be less than 49 days, 17 hours, 2 minutes, 47 seconds, 294 milliseconds + /// in order to not overflow the Timer used to track authorization refresh. + /// + /// + private static TimeSpan MaximumAuthorizationRefresh { get; } = TimeSpan.FromDays(49); + /// /// The amount time to allow to refresh authorization of an AMQP link. /// @@ -893,7 +905,13 @@ protected virtual TimeSpan CalculateLinkAuthorizationRefreshInterval( currentTimeUtc ??= DateTime.UtcNow; var refreshDueInterval = (expirationTimeUtc.Subtract(AuthorizationRefreshBuffer)).Subtract(currentTimeUtc.Value); - return (refreshDueInterval < MinimumAuthorizationRefresh) ? MinimumAuthorizationRefresh : refreshDueInterval; + + return refreshDueInterval switch + { + _ when (refreshDueInterval < MinimumAuthorizationRefresh) => MinimumAuthorizationRefresh, + _ when (refreshDueInterval > MaximumAuthorizationRefresh) => MaximumAuthorizationRefresh, + _ => refreshDueInterval + }; } /// diff --git a/sdk/servicebus/Azure.Messaging.ServiceBus/tests/Amqp/AmqpConnectionScopeTests.cs b/sdk/servicebus/Azure.Messaging.ServiceBus/tests/Amqp/AmqpConnectionScopeTests.cs index da4750d4f11d..7ceb7de5b533 100644 --- a/sdk/servicebus/Azure.Messaging.ServiceBus/tests/Amqp/AmqpConnectionScopeTests.cs +++ b/sdk/servicebus/Azure.Messaging.ServiceBus/tests/Amqp/AmqpConnectionScopeTests.cs @@ -43,6 +43,43 @@ public void CalculateLinkAuthorizationRefreshIntervalRespectsTheRefreshBuffer() Assert.That(calculatedExpire, Is.EqualTo(expireTime.Subtract(buffer)).Within(TimeSpan.FromSeconds(2)), "The authorization buffer should have been used for buffering."); } + /// + /// Verifies functionality of the + /// method. + /// + /// + [Test] + public void CalculateLinkAuthorizationRefreshIntervalRespectsTheMinimumDuration() + { + var credential = new Mock(Mock.Of(), "{namespace}.servicebus.windows.net"); + var mockScope = new MockConnectionMockScope(new Uri("sb://mine.hubs.com"), credential.Object, ServiceBusTransportType.AmqpTcp, null); + var currentTime = new DateTime(2015, 10, 27, 00, 00, 00); + var minimumRefresh = GetMinimumAuthorizationRefresh(); + var expireTime = currentTime.Add(minimumRefresh.Subtract(TimeSpan.FromMilliseconds(500))); + var calculatedRefresh = mockScope.InvokeCalculateLinkAuthorizationRefreshInterval(expireTime, currentTime); + + Assert.That(calculatedRefresh, Is.EqualTo(minimumRefresh), "The minimum refresh duration should have been used."); + } + + /// + /// Verifies functionality of the + /// method. + /// + /// + [Test] + public void CalculateLinkAuthorizationRefreshIntervalRespectsTheMaximumDuration() + { + var credential = new Mock(Mock.Of(), "{namespace}.servicebus.windows.net"); + var mockScope = new MockConnectionMockScope(new Uri("sb://mine.hubs.com"), credential.Object, ServiceBusTransportType.AmqpTcp, null); + var currentTime = new DateTime(2015, 10, 27, 00, 00, 00); + var refreshBuffer = GetAuthorizationRefreshBuffer(); + var maximumRefresh = GetMaximumAuthorizationRefresh(); + var expireTime = currentTime.Add(maximumRefresh.Add(refreshBuffer).Add(TimeSpan.FromMilliseconds(500))); + var calculatedRefresh = mockScope.InvokeCalculateLinkAuthorizationRefreshInterval(expireTime, currentTime); + + Assert.That(calculatedRefresh, Is.EqualTo(maximumRefresh), "The maximum refresh duration should have been used."); + } + /// /// Gets the token refresh buffer for the scope, using the /// private property accessor. @@ -54,6 +91,28 @@ private static TimeSpan GetAuthorizationRefreshBuffer() => .GetProperty("AuthorizationRefreshBuffer", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.GetProperty) .GetValue(null); + /// + /// Gets the minimum authorization refresh interval, using the + /// private property accessor. + /// + /// + private static TimeSpan GetMinimumAuthorizationRefresh() => + (TimeSpan) + typeof(AmqpConnectionScope) + .GetProperty("MinimumAuthorizationRefresh", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.GetProperty) + .GetValue(null); + + /// + /// Gets the maximum authorization refresh interval, using the + /// private property accessor. + /// + /// + private static TimeSpan GetMaximumAuthorizationRefresh() => + (TimeSpan) + typeof(AmqpConnectionScope) + .GetProperty("MaximumAuthorizationRefresh", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.GetProperty) + .GetValue(null); + /// /// Creates a set of dummy settings for testing purposes. ///