Skip to content

Commit

Permalink
Add RateLimiting APIs (#61788)
Browse files Browse the repository at this point in the history
  • Loading branch information
BrennanConroy committed Dec 3, 2021
1 parent 62b2333 commit 0540772
Show file tree
Hide file tree
Showing 21 changed files with 2,710 additions and 1 deletion.
1 change: 1 addition & 0 deletions docs/area-owners.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ Note: Editing this file doesn't update the mapping used by the `@msftbot` issue
| area-System.Text.RegularExpressions | @ericstj | @buyaa-n @joperezr @steveharter | Consultants: @stephentoub |
| area-System.Threading | @mangod9 | @kouvel | |
| area-System.Threading.Channels | @ericstj | @buyaa-n @joperezr @steveharter | Consultants: @stephentoub |
| area-System.Threading.RateLimiting | @rafikiassumani-msft | @BrennanConroy @halter73 | Consultants: @eerhardt |
| area-System.Threading.Tasks | @ericstj | @buyaa-n @joperezr @steveharter | Consultants: @stephentoub |
| area-System.Transactions | @HongGit | @HongGit | |
| area-System.Xml | @jeffhandley | @eiriktsarpalis @krwq @layomia | |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,17 @@ public T PeekHead()
return _array[_head];
}

public T PeekTail()
{
Debug.Assert(!IsEmpty); // caller's responsibility to make sure there are elements remaining
var index = _tail - 1;
if (index == -1)
{
index = _array.Length - 1;
}
return _array[index];
}

public T DequeueTail()
{
Debug.Assert(!IsEmpty); // caller's responsibility to make sure there are elements remaining
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ System.Threading.Channel&lt;T&gt;</PackageDescription>
</PropertyGroup>
<ItemGroup>
<Compile Include="System\VoidResult.cs" />
<Compile Include="System\Collections\Generic\Deque.cs" />
<Compile Include="System\Threading\Channels\AsyncOperation.cs" />
<Compile Include="System\Threading\Channels\AsyncOperation.netcoreapp.cs"
Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp'" />
Expand Down Expand Up @@ -40,6 +39,8 @@ System.Threading.Channel&lt;T&gt;</PackageDescription>
Link="Common\Internal\Padding.cs" />
<Compile Include="$(CommonPath)System\Collections\Concurrent\SingleProducerConsumerQueue.cs"
Link="Common\System\Collections\Concurrent\SingleProducerConsumerQueue.cs" />
<Compile Include="$(CommonPath)System\Collections\Generic\Deque.cs"
Link="Common\System\Collections\Generic\Deque.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp'">
<Reference Include="System.Collections" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "..\Common\tests\TestUtilities\TestUtilities.csproj", "{CAEE0409-CCC3-4EA6-AB54-177FD305D42D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bcl.AsyncInterfaces", "..\Microsoft.Bcl.AsyncInterfaces\ref\Microsoft.Bcl.AsyncInterfaces.csproj", "{39DA5B84-ECA2-42A2-BEBD-C056BDB8AD53}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bcl.AsyncInterfaces", "..\Microsoft.Bcl.AsyncInterfaces\src\Microsoft.Bcl.AsyncInterfaces.csproj", "{F59F4FD7-EA00-47EA-A09A-6F76CB079F9B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.CompilerServices.Unsafe", "..\System.Runtime.CompilerServices.Unsafe\ref\System.Runtime.CompilerServices.Unsafe.csproj", "{0D1C7DCB-970D-4099-AC9F-A01E75923EC6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.CompilerServices.Unsafe", "..\System.Runtime.CompilerServices.Unsafe\src\System.Runtime.CompilerServices.Unsafe.ilproj", "{AF838F1D-5C1C-472B-B31C-9A3B7507BB4B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Interop.DllImportGenerator", "..\System.Runtime.InteropServices\gen\DllImportGenerator\DllImportGenerator.csproj", "{1E52F495-578C-4FDB-86DD-87EAAE0A0BE7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Interop.SourceGeneration", "..\System.Runtime.InteropServices\gen\Microsoft.Interop.SourceGeneration\Microsoft.Interop.SourceGeneration.csproj", "{25495BDC-0614-4FAC-B6EA-DF3F0E35A871}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Threading.RateLimiting", "ref\System.Threading.RateLimiting.csproj", "{FD274A80-0D68-48A0-9AC7-279C9E69BC63}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Threading.RateLimiting", "src\System.Threading.RateLimiting.csproj", "{CD96AFE9-0F7F-42FA-BBDA-F57EDCBB4609}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Threading.RateLimiting.Tests", "tests\System.Threading.RateLimiting.Tests.csproj", "{AE81EE9F-1240-4AF1-BF21-7F451B7859E5}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{6614EF7F-23FC-4809-AFF5-1ADBF1B6422C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{111B1B5B-A004-4C05-9A8C-E0931DADA5FB}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{85204CF5-0C88-4BBB-9E70-D8CCED82ED3D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{CAEE0409-CCC3-4EA6-AB54-177FD305D42D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CAEE0409-CCC3-4EA6-AB54-177FD305D42D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CAEE0409-CCC3-4EA6-AB54-177FD305D42D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CAEE0409-CCC3-4EA6-AB54-177FD305D42D}.Release|Any CPU.Build.0 = Release|Any CPU
{39DA5B84-ECA2-42A2-BEBD-C056BDB8AD53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{39DA5B84-ECA2-42A2-BEBD-C056BDB8AD53}.Debug|Any CPU.Build.0 = Debug|Any CPU
{39DA5B84-ECA2-42A2-BEBD-C056BDB8AD53}.Release|Any CPU.ActiveCfg = Release|Any CPU
{39DA5B84-ECA2-42A2-BEBD-C056BDB8AD53}.Release|Any CPU.Build.0 = Release|Any CPU
{F59F4FD7-EA00-47EA-A09A-6F76CB079F9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F59F4FD7-EA00-47EA-A09A-6F76CB079F9B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F59F4FD7-EA00-47EA-A09A-6F76CB079F9B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F59F4FD7-EA00-47EA-A09A-6F76CB079F9B}.Release|Any CPU.Build.0 = Release|Any CPU
{0D1C7DCB-970D-4099-AC9F-A01E75923EC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0D1C7DCB-970D-4099-AC9F-A01E75923EC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0D1C7DCB-970D-4099-AC9F-A01E75923EC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0D1C7DCB-970D-4099-AC9F-A01E75923EC6}.Release|Any CPU.Build.0 = Release|Any CPU
{AF838F1D-5C1C-472B-B31C-9A3B7507BB4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AF838F1D-5C1C-472B-B31C-9A3B7507BB4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AF838F1D-5C1C-472B-B31C-9A3B7507BB4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AF838F1D-5C1C-472B-B31C-9A3B7507BB4B}.Release|Any CPU.Build.0 = Release|Any CPU
{1E52F495-578C-4FDB-86DD-87EAAE0A0BE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1E52F495-578C-4FDB-86DD-87EAAE0A0BE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1E52F495-578C-4FDB-86DD-87EAAE0A0BE7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1E52F495-578C-4FDB-86DD-87EAAE0A0BE7}.Release|Any CPU.Build.0 = Release|Any CPU
{25495BDC-0614-4FAC-B6EA-DF3F0E35A871}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{25495BDC-0614-4FAC-B6EA-DF3F0E35A871}.Debug|Any CPU.Build.0 = Debug|Any CPU
{25495BDC-0614-4FAC-B6EA-DF3F0E35A871}.Release|Any CPU.ActiveCfg = Release|Any CPU
{25495BDC-0614-4FAC-B6EA-DF3F0E35A871}.Release|Any CPU.Build.0 = Release|Any CPU
{FD274A80-0D68-48A0-9AC7-279C9E69BC63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FD274A80-0D68-48A0-9AC7-279C9E69BC63}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FD274A80-0D68-48A0-9AC7-279C9E69BC63}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FD274A80-0D68-48A0-9AC7-279C9E69BC63}.Release|Any CPU.Build.0 = Release|Any CPU
{CD96AFE9-0F7F-42FA-BBDA-F57EDCBB4609}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CD96AFE9-0F7F-42FA-BBDA-F57EDCBB4609}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CD96AFE9-0F7F-42FA-BBDA-F57EDCBB4609}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CD96AFE9-0F7F-42FA-BBDA-F57EDCBB4609}.Release|Any CPU.Build.0 = Release|Any CPU
{AE81EE9F-1240-4AF1-BF21-7F451B7859E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AE81EE9F-1240-4AF1-BF21-7F451B7859E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AE81EE9F-1240-4AF1-BF21-7F451B7859E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AE81EE9F-1240-4AF1-BF21-7F451B7859E5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{CAEE0409-CCC3-4EA6-AB54-177FD305D42D} = {6614EF7F-23FC-4809-AFF5-1ADBF1B6422C}
{AE81EE9F-1240-4AF1-BF21-7F451B7859E5} = {6614EF7F-23FC-4809-AFF5-1ADBF1B6422C}
{39DA5B84-ECA2-42A2-BEBD-C056BDB8AD53} = {111B1B5B-A004-4C05-9A8C-E0931DADA5FB}
{0D1C7DCB-970D-4099-AC9F-A01E75923EC6} = {111B1B5B-A004-4C05-9A8C-E0931DADA5FB}
{FD274A80-0D68-48A0-9AC7-279C9E69BC63} = {111B1B5B-A004-4C05-9A8C-E0931DADA5FB}
{F59F4FD7-EA00-47EA-A09A-6F76CB079F9B} = {85204CF5-0C88-4BBB-9E70-D8CCED82ED3D}
{AF838F1D-5C1C-472B-B31C-9A3B7507BB4B} = {85204CF5-0C88-4BBB-9E70-D8CCED82ED3D}
{1E52F495-578C-4FDB-86DD-87EAAE0A0BE7} = {85204CF5-0C88-4BBB-9E70-D8CCED82ED3D}
{25495BDC-0614-4FAC-B6EA-DF3F0E35A871} = {85204CF5-0C88-4BBB-9E70-D8CCED82ED3D}
{CD96AFE9-0F7F-42FA-BBDA-F57EDCBB4609} = {85204CF5-0C88-4BBB-9E70-D8CCED82ED3D}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {25036AEF-71B3-4C8A-891F-0350414F9A23}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// ------------------------------------------------------------------------------
// Changes to this file must follow the https://aka.ms/api-review process.
// ------------------------------------------------------------------------------

namespace System.Threading.RateLimiting
{
public sealed partial class ConcurrencyLimiter : System.Threading.RateLimiting.RateLimiter
{
public ConcurrencyLimiter(System.Threading.RateLimiting.ConcurrencyLimiterOptions options) { }
protected override System.Threading.RateLimiting.RateLimitLease AcquireCore(int permitCount) { throw null; }
protected override void Dispose(bool disposing) { }
protected override System.Threading.Tasks.ValueTask DisposeAsyncCore() { throw null; }
public override int GetAvailablePermits() { throw null; }
protected override System.Threading.Tasks.ValueTask<System.Threading.RateLimiting.RateLimitLease> WaitAsyncCore(int permitCount, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
}
public sealed partial class ConcurrencyLimiterOptions
{
public ConcurrencyLimiterOptions(int permitLimit, System.Threading.RateLimiting.QueueProcessingOrder queueProcessingOrder, int queueLimit) { }
public int PermitLimit { get { throw null; } }
public int QueueLimit { get { throw null; } }
public System.Threading.RateLimiting.QueueProcessingOrder QueueProcessingOrder { get { throw null; } }
}
public static partial class MetadataName
{
public static System.Threading.RateLimiting.MetadataName<string> ReasonPhrase { get { throw null; } }
public static System.Threading.RateLimiting.MetadataName<System.TimeSpan> RetryAfter { get { throw null; } }
public static System.Threading.RateLimiting.MetadataName<T> Create<T>(string name) { throw null; }
}
public sealed partial class MetadataName<T> : System.IEquatable<System.Threading.RateLimiting.MetadataName<T>>
{
public MetadataName(string name) { }
public string Name { get { throw null; } }
public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; }
public bool Equals(System.Threading.RateLimiting.MetadataName<T>? other) { throw null; }
public override int GetHashCode() { throw null; }
public static bool operator ==(System.Threading.RateLimiting.MetadataName<T> left, System.Threading.RateLimiting.MetadataName<T> right) { throw null; }
public static bool operator !=(System.Threading.RateLimiting.MetadataName<T> left, System.Threading.RateLimiting.MetadataName<T> right) { throw null; }
public override string ToString() { throw null; }
}
public enum QueueProcessingOrder
{
OldestFirst = 0,
NewestFirst = 1,
}
public abstract partial class RateLimiter : System.IAsyncDisposable, System.IDisposable
{
protected RateLimiter() { }
public System.Threading.RateLimiting.RateLimitLease Acquire(int permitCount = 1) { throw null; }
protected abstract System.Threading.RateLimiting.RateLimitLease AcquireCore(int permitCount);
public void Dispose() { }
protected virtual void Dispose(bool disposing) { }
public System.Threading.Tasks.ValueTask DisposeAsync() { throw null; }
protected virtual System.Threading.Tasks.ValueTask DisposeAsyncCore() { throw null; }
public abstract int GetAvailablePermits();
public System.Threading.Tasks.ValueTask<System.Threading.RateLimiting.RateLimitLease> WaitAsync(int permitCount = 1, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
protected abstract System.Threading.Tasks.ValueTask<System.Threading.RateLimiting.RateLimitLease> WaitAsyncCore(int permitCount, System.Threading.CancellationToken cancellationToken);
}
public abstract partial class RateLimitLease : System.IDisposable
{
protected RateLimitLease() { }
public abstract bool IsAcquired { get; }
public abstract System.Collections.Generic.IEnumerable<string> MetadataNames { get; }
public void Dispose() { }
protected virtual void Dispose(bool disposing) { }
public virtual System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, object?>> GetAllMetadata() { throw null; }
public abstract bool TryGetMetadata(string metadataName, out object? metadata);
public bool TryGetMetadata<T>(System.Threading.RateLimiting.MetadataName<T> metadataName, [System.Diagnostics.CodeAnalysis.MaybeNullAttribute] out T metadata) { throw null; }
}
public sealed partial class TokenBucketRateLimiter : System.Threading.RateLimiting.RateLimiter
{
public TokenBucketRateLimiter(System.Threading.RateLimiting.TokenBucketRateLimiterOptions options) { }
protected override System.Threading.RateLimiting.RateLimitLease AcquireCore(int tokenCount) { throw null; }
protected override void Dispose(bool disposing) { }
protected override System.Threading.Tasks.ValueTask DisposeAsyncCore() { throw null; }
public override int GetAvailablePermits() { throw null; }
public bool TryReplenish() { throw null; }
protected override System.Threading.Tasks.ValueTask<System.Threading.RateLimiting.RateLimitLease> WaitAsyncCore(int tokenCount, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
}
public sealed partial class TokenBucketRateLimiterOptions
{
public TokenBucketRateLimiterOptions(int tokenLimit, System.Threading.RateLimiting.QueueProcessingOrder queueProcessingOrder, int queueLimit, System.TimeSpan replenishmentPeriod, int tokensPerPeriod, bool autoReplenishment = true) { }
public bool AutoReplenishment { get { throw null; } }
public int QueueLimit { get { throw null; } }
public System.Threading.RateLimiting.QueueProcessingOrder QueueProcessingOrder { get { throw null; } }
public System.TimeSpan ReplenishmentPeriod { get { throw null; } }
public int TokenLimit { get { throw null; } }
public int TokensPerPeriod { get { throw null; } }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$(NetCoreAppCurrent);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum)</TargetFrameworks>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Compile Include="System.Threading.RateLimiting.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == '$(NetCoreAppCurrent)'">
<ProjectReference Include="$(LibrariesProjectRoot)System.Runtime\ref\System.Runtime.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' and '$(TargetFramework)' != '$(NetCoreAppCurrent)'">
<Reference Include="System.Runtime" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' != '.NETCoreApp'">
<PackageReference Include="System.Threading.Tasks.Extensions" Version="$(SystemThreadingTasksExtensionsVersion)" />
</ItemGroup>
<ItemGroup Condition="!$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'netstandard2.1'))">
<ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Bcl.AsyncInterfaces\ref\Microsoft.Bcl.AsyncInterfaces.csproj" />
</ItemGroup>
</Project>
Loading

0 comments on commit 0540772

Please sign in to comment.