Пример #1
0
        public async Task Invoke(HttpContext context)
        {
            CapacityCheckResult checkResult = _capacityGuard.CheckCapacity(context.RequestAborted);

            if (!checkResult.ExecutionAllowed)
            {
                EnqueueStatus enqueueStatus = await checkResult.QueueTask; // this is the place task waits in queue

                // execution cancelled or queue timeout reached or queue full
                if (enqueueStatus != EnqueueStatus.AllowExecution && !context.RequestAborted.IsCancellationRequested)
                {
                    var responseFeature = context.Features.Get <IHttpResponseFeature>();
                    responseFeature.StatusCode   = StatusCodes.Status429TooManyRequests;
                    responseFeature.ReasonPhrase = enqueueStatus.ToString();

                    return;
                }
            }

            try
            {
                await _next(context);
            }
            finally
            {
                _capacityGuard.FinishExecution();
            }
        }
        public CapacityCheckResult CheckCapacity(CancellationToken requestAbortedCancellationToken)
        {
            try
            {
                CancellationToken enqueueCancellationToken = GetEnqueueCancellationToken(requestAbortedCancellationToken);

                _guardSemaphore.Wait(enqueueCancellationToken);

                if (_concurrentRequestsCount < _throttlingConfiguration.ConcurrentRequestsLimit)
                {
                    ++_concurrentRequestsCount;
                    return(CapacityCheckResult.GetAllowed());
                }

                return(CapacityCheckResult.GetQueued(Enqueue(enqueueCancellationToken)));
            }
            catch (OperationCanceledException)
            {
                return(CapacityCheckResult.GetCancelled());
            }
            finally
            {
                _guardSemaphore.Release();
            }
        }