Skip to content

Commit

Permalink
Add new issue that demonstrates how to use PartitionedRateLimiter
Browse files Browse the repository at this point in the history
  • Loading branch information
martintmk authored Jul 4, 2023
1 parent 2de8fc0 commit ed4c480
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using System.Threading.RateLimiting;
using Microsoft.Extensions.DependencyInjection;
using Polly.RateLimiting;
using Polly.Registry;

namespace Polly.Extensions.Tests.Issues;

public partial class IssuesTests
{
/// <summary>
/// This test demonstrates how to use <see cref="PartitionedRateLimiter"/> to rate-limit the individual users.
/// Additionally, it also shows how to disable rate limiting for admin users.
/// </summary>
[Fact]
public async void PartitionedRateLimiter_EnsureUserLimited_1365()
{
// arrange
var userKey = new ResiliencePropertyKey<string>("user");
var services = new ServiceCollection();
services
.AddResilienceStrategy("shared-limiter", (builder, context) =>
{
var partitionedLimiter = PartitionedRateLimiter.Create<ResilienceContext, string>(context =>
{
// you can use `context.ServiceProvider` to resolve whatever service you
// want form DI such as `IHttpContextAccessor` and use it here to resolve
// any information from HttpContext
if (!context.Properties.TryGetValue(userKey, out var user) || user == "admin")
{
return RateLimitPartition.GetNoLimiter("none");
}
return RateLimitPartition.GetConcurrencyLimiter(user, key => new ConcurrencyLimiterOptions { PermitLimit = 2, QueueLimit = 0 });
});
builder.AddRateLimiter(new RateLimiterStrategyOptions
{
RateLimiter = ResilienceRateLimiter.Create(partitionedLimiter)
});
});

var serviceProvider = services.BuildServiceProvider();
var strategy = serviceProvider.GetRequiredService<ResilienceStrategyProvider<string>>().GetStrategy("shared-limiter");

// assert user is limited
using var asserted = new ManualResetEvent(false);
await Assert.ThrowsAsync<RateLimiterRejectedException>(() => ExecuteBatch("guest-user", asserted));
asserted.Set();

// assert admin is not limited
using var adminAsserted = new ManualResetEvent(false);
var task = ExecuteBatch("admin", adminAsserted);
task.Wait(100).Should().BeFalse();
adminAsserted.Set();
await task;

async Task ExecuteBatch(string user, ManualResetEvent waitAsserted)
{
var tasks = Enumerable.Repeat(0, 10).Select(_ =>
{
return Task.Run(async () =>
{
var context = ResilienceContext.Get();
context.Properties.Set(userKey, user);
await strategy.ExecuteAsync(async _ =>
{
await Task.Yield();
waitAsserted.WaitOne();
},
context);
});
}).ToArray();

var finished = await Task.WhenAny(tasks);
await finished;
}
}
}
1 change: 1 addition & 0 deletions test/Polly.Extensions.Tests/Polly.Extensions.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<ItemGroup>
<Using Include="Polly.TestUtils" />
<ProjectReference Include="..\..\src\Polly.Extensions\Polly.Extensions.csproj" />
<ProjectReference Include="..\..\src\Polly.RateLimiting\Polly.RateLimiting.csproj" />
<ProjectReference Include="..\Polly.TestUtils\Polly.TestUtils.csproj" />
<PackageReference Include="Microsoft.Extensions.Configuration" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" />
Expand Down

0 comments on commit ed4c480

Please sign in to comment.