| File: System\Threading\RateLimiting\PartitionedRateLimiter.cs | Web Access |
| Project: src\runtime\src\libraries\System.Threading.RateLimiting\src\System.Threading.RateLimiting.csproj (System.Threading.RateLimiting) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; namespace System.Threading.RateLimiting { /// <summary> /// Contains methods to assist with creating a <see cref="PartitionedRateLimiter{TResource}"/>. /// </summary> public static class PartitionedRateLimiter { /// <summary> /// Method used to create a default implementation of <see cref="PartitionedRateLimiter{TResource}"/>. /// </summary> /// <typeparam name="TResource">The resource type that is being rate limited.</typeparam> /// <typeparam name="TPartitionKey">The type to distinguish partitions with.</typeparam> /// <param name="partitioner">Method called every time an Acquire or WaitAsync call is made to figure out what rate limiter to apply to the request. /// If the <see cref="RateLimitPartition{TKey}.PartitionKey"/> matches a cached entry then the rate limiter previously used for that key is used. Otherwise, the factory is called to get a new rate limiter.</param> /// <param name="equalityComparer">Optional <see cref="IEqualityComparer{T}"/> to customize the comparison logic for <typeparamref name="TPartitionKey"/>.</param> /// <returns></returns> public static PartitionedRateLimiter<TResource> Create<TResource, TPartitionKey>( Func<TResource, RateLimitPartition<TPartitionKey>> partitioner, IEqualityComparer<TPartitionKey>? equalityComparer = null) where TPartitionKey : notnull { return new DefaultPartitionedRateLimiter<TResource, TPartitionKey>(partitioner, equalityComparer); } /// <summary> /// Creates a single <see cref="PartitionedRateLimiter{TResource}"/> that wraps the passed in <see cref="PartitionedRateLimiter{TResource}"/>s. /// </summary> /// <remarks> /// <para> /// Methods on the returned <see cref="PartitionedRateLimiter{TResource}"/> will iterate over the passed in <paramref name="limiters"/> in the order given. /// </para> /// <para> /// <see cref="PartitionedRateLimiter{TResource}.GetStatistics(TResource)"/> will return the lowest value for <see cref="RateLimiterStatistics.CurrentAvailablePermits"/>, /// the inner-most limiter's <see cref="RateLimiterStatistics.TotalSuccessfulLeases"/>, /// and the aggregate values for the rest of the properties from the <paramref name="limiters"/>. /// </para> /// <para> /// <see cref="RateLimitLease"/>s returned will aggregate metadata and for duplicates use the value of the first lease with the same metadata name. /// </para> /// <para> /// Disposing the returned <see cref="PartitionedRateLimiter{TResource}"/> does not dispose the inner <paramref name="limiters"/>. /// Callers are expected to dispose the inner limiters themselves once they are no longer in use. /// </para> /// </remarks> /// <typeparam name="TResource">The resource type that is being rate limited.</typeparam> /// <param name="limiters">The <see cref="PartitionedRateLimiter{TResource}"/>s that will be called in order when acquiring resources.</param> /// <returns></returns> /// <exception cref="ArgumentNullException"><paramref name="limiters"/> is a null parameter.</exception> /// <exception cref="ArgumentException"><paramref name="limiters"/> is an empty array.</exception> public static PartitionedRateLimiter<TResource> CreateChained<TResource>( params PartitionedRateLimiter<TResource>[] limiters) { ArgumentNullException.ThrowIfNull(limiters); if (limiters.Length == 0) { throw new ArgumentException("Must pass in at least 1 limiter.", nameof(limiters)); } return new ChainedPartitionedRateLimiter<TResource>(limiters); } } }