diff --git a/src/Middleware/ConcurrencyLimiter/src/QueuePolicies/QueuePolicy.cs b/src/Middleware/ConcurrencyLimiter/src/QueuePolicies/QueuePolicy.cs index aec06f6eb6..08d6338df2 100644 --- a/src/Middleware/ConcurrencyLimiter/src/QueuePolicies/QueuePolicy.cs +++ b/src/Middleware/ConcurrencyLimiter/src/QueuePolicies/QueuePolicy.cs @@ -10,31 +10,35 @@ namespace Microsoft.AspNetCore.ConcurrencyLimiter { internal class QueuePolicy : IQueuePolicy, IDisposable { - private readonly int _maxConcurrentRequests; - private readonly int _requestQueueLimit; + private readonly int _maxTotalRequest; private readonly SemaphoreSlim _serverSemaphore; private object _totalRequestsLock = new object(); + public int TotalRequests { get; private set; } public QueuePolicy(IOptions options) { - _maxConcurrentRequests = options.Value.MaxConcurrentRequests; - if (_maxConcurrentRequests <= 0) + var queuePolicyOptions = options.Value; + + var maxConcurrentRequests = queuePolicyOptions.MaxConcurrentRequests; + if (maxConcurrentRequests <= 0) { - throw new ArgumentException(nameof(_maxConcurrentRequests), "MaxConcurrentRequests must be a positive integer."); + throw new ArgumentException(nameof(maxConcurrentRequests), "MaxConcurrentRequests must be a positive integer."); } - _requestQueueLimit = options.Value.RequestQueueLimit; - if (_requestQueueLimit < 0) + var requestQueueLimit = queuePolicyOptions.RequestQueueLimit; + if (requestQueueLimit < 0) { - throw new ArgumentException(nameof(_requestQueueLimit), "The RequestQueueLimit cannot be a negative number."); + throw new ArgumentException(nameof(requestQueueLimit), "The RequestQueueLimit cannot be a negative number."); } - _serverSemaphore = new SemaphoreSlim(_maxConcurrentRequests); + _serverSemaphore = new SemaphoreSlim(maxConcurrentRequests); + + _maxTotalRequest = maxConcurrentRequests + requestQueueLimit; } - public async ValueTask TryEnterAsync() + public ValueTask TryEnterAsync() { // a return value of 'false' indicates that the request is rejected // a return value of 'true' indicates that the request may proceed @@ -42,17 +46,21 @@ namespace Microsoft.AspNetCore.ConcurrencyLimiter lock (_totalRequestsLock) { - if (TotalRequests >= _requestQueueLimit + _maxConcurrentRequests) + if (TotalRequests >= _maxTotalRequest) { - return false; + return new ValueTask(false); } TotalRequests++; } - await _serverSemaphore.WaitAsync(); + Task task = _serverSemaphore.WaitAsync(); + if (task.IsCompletedSuccessfully) + { + return new ValueTask(true); + } - return true; + return SemaphoreAwaited(task); } public void OnExit() @@ -69,5 +77,12 @@ namespace Microsoft.AspNetCore.ConcurrencyLimiter { _serverSemaphore.Dispose(); } + + private async ValueTask SemaphoreAwaited(Task task) + { + await task; + + return true; + } } } diff --git a/src/Middleware/ConcurrencyLimiter/src/QueuePolicies/StackPolicy.cs b/src/Middleware/ConcurrencyLimiter/src/QueuePolicies/StackPolicy.cs index 557aedfac4..5dcd5927d1 100644 --- a/src/Middleware/ConcurrencyLimiter/src/QueuePolicies/StackPolicy.cs +++ b/src/Middleware/ConcurrencyLimiter/src/QueuePolicies/StackPolicy.cs @@ -21,8 +21,6 @@ namespace Microsoft.AspNetCore.ConcurrencyLimiter private readonly object _bufferLock = new Object(); - private readonly static ValueTask _trueTask = new ValueTask(true); - private int _freeServerSpots; public StackPolicy(IOptions options) @@ -40,7 +38,7 @@ namespace Microsoft.AspNetCore.ConcurrencyLimiter if (_freeServerSpots > 0) { _freeServerSpots--; - return _trueTask; + return new ValueTask(true); } // if queue is full, cancel oldest request