@@ -10,49 +10,57 @@ namespace Microsoft.AspNetCore.ConcurrencyLimiter
10
10
{
11
11
internal class QueuePolicy : IQueuePolicy , IDisposable
12
12
{
13
- private readonly int _maxConcurrentRequests ;
14
- private readonly int _requestQueueLimit ;
13
+ private readonly int _maxTotalRequest ;
15
14
private readonly SemaphoreSlim _serverSemaphore ;
16
15
17
16
private object _totalRequestsLock = new object ( ) ;
17
+
18
18
public int TotalRequests { get ; private set ; }
19
19
20
20
public QueuePolicy ( IOptions < QueuePolicyOptions > options )
21
21
{
22
- _maxConcurrentRequests = options . Value . MaxConcurrentRequests ;
23
- if ( _maxConcurrentRequests <= 0 )
22
+ var queuePolicyOptions = options . Value ;
23
+
24
+ var maxConcurrentRequests = queuePolicyOptions . MaxConcurrentRequests ;
25
+ if ( maxConcurrentRequests <= 0 )
24
26
{
25
- throw new ArgumentException ( nameof ( _maxConcurrentRequests ) , "MaxConcurrentRequests must be a positive integer." ) ;
27
+ throw new ArgumentException ( nameof ( maxConcurrentRequests ) , "MaxConcurrentRequests must be a positive integer." ) ;
26
28
}
27
29
28
- _requestQueueLimit = options . Value . RequestQueueLimit ;
29
- if ( _requestQueueLimit < 0 )
30
+ var requestQueueLimit = queuePolicyOptions . RequestQueueLimit ;
31
+ if ( requestQueueLimit < 0 )
30
32
{
31
- throw new ArgumentException ( nameof ( _requestQueueLimit ) , "The RequestQueueLimit cannot be a negative number." ) ;
33
+ throw new ArgumentException ( nameof ( requestQueueLimit ) , "The RequestQueueLimit cannot be a negative number." ) ;
32
34
}
33
35
34
- _serverSemaphore = new SemaphoreSlim ( _maxConcurrentRequests ) ;
36
+ _serverSemaphore = new SemaphoreSlim ( maxConcurrentRequests ) ;
37
+
38
+ _maxTotalRequest = maxConcurrentRequests + requestQueueLimit ;
35
39
}
36
40
37
- public async ValueTask < bool > TryEnterAsync ( )
41
+ public ValueTask < bool > TryEnterAsync ( )
38
42
{
39
43
// a return value of 'false' indicates that the request is rejected
40
44
// a return value of 'true' indicates that the request may proceed
41
45
// _serverSemaphore.Release is *not* called in this method, it is called externally when requests leave the server
42
46
43
47
lock ( _totalRequestsLock )
44
48
{
45
- if ( TotalRequests >= _requestQueueLimit + _maxConcurrentRequests )
49
+ if ( TotalRequests >= _maxTotalRequest )
46
50
{
47
- return false ;
51
+ return new ValueTask < bool > ( false ) ;
48
52
}
49
53
50
54
TotalRequests ++ ;
51
55
}
52
56
53
- await _serverSemaphore . WaitAsync ( ) ;
57
+ Task task = _serverSemaphore . WaitAsync ( ) ;
58
+ if ( task . IsCompletedSuccessfully )
59
+ {
60
+ return new ValueTask < bool > ( true ) ;
61
+ }
54
62
55
- return true ;
63
+ return SemaphoreAwaited ( task ) ;
56
64
}
57
65
58
66
public void OnExit ( )
@@ -69,5 +77,12 @@ public void Dispose()
69
77
{
70
78
_serverSemaphore . Dispose ( ) ;
71
79
}
80
+
81
+ private async ValueTask < bool > SemaphoreAwaited ( Task task )
82
+ {
83
+ await task ;
84
+
85
+ return true ;
86
+ }
72
87
}
73
88
}
0 commit comments