System.Threading.RateLimiting limiter's algorithms are using an internal queue, for queueing async acquire permit requests.
There are some missing calls to disposed of queued requests cancellation token registration after setting their result.
In general, limiters try to dequeue one request from the queue and set the result of the request with a failed or successful lease.
For example, in the replenishments phase(ReplenishInternal), the limiter dequeues one request and, after setting its result, disposes of its cancellation token registration object(nextPendingRequest.CancellationTokenRegistration.Dispose();). also limiter followe same bahvior on Dispose method(next.CancellationTokenRegistration.Dispose();).
private void ReplenishInternal(long nowTicks)
{
...
nextPendingRequest = _options.QueueProcessingOrder == QueueProcessingOrder.OldestFirst
? _queue.DequeueHead()
: _queue.DequeueTail();
if (!nextPendingRequest.Tcs.TrySetResult(SuccessfulLease)){ ... }
else { ... }
nextPendingRequest.CancellationTokenRegistration.Dispose();
}
The limiters should follow the same behavior in the other places, such as when they try to dequeue old requests in order to free some space for pushing new requests on the queue with the newest first processing order policy.
protected override ValueTask<RateLimitLease> AcquireAsyncCore(int permitCount, CancellationToken cancellationToken = default)
{
...
if (_options.QueueProcessingOrder == QueueProcessingOrder.NewestFirst && permitCount <= _options.QueueLimit){
RequestRegistration oldestRequest = _queue.DequeueHead();
if (!oldestRequest.Tcs.TrySetResult(FailedLease)){ ... }
else { ... }
// Mising dispose
// oldestRequest.CancellationTokenRegistration.Dispose();
}
}
System.Threading.RateLimitinglimiter's algorithms are using an internal queue, for queueing async acquire permit requests.There are some missing calls to disposed of queued requests cancellation token registration after setting their result.
In general, limiters try to dequeue one request from the queue and set the result of the request with a failed or successful lease.
For example, in the replenishments phase(
ReplenishInternal), the limiter dequeues one request and, after setting its result, disposes of its cancellation token registration object(nextPendingRequest.CancellationTokenRegistration.Dispose();). also limiter followe same bahvior onDisposemethod(next.CancellationTokenRegistration.Dispose();).The limiters should follow the same behavior in the other places, such as when they try to dequeue old requests in order to free some space for pushing new requests on the queue with the newest first processing order policy.