Uh oh!
There was an error while loading. Please reload this page.
Add RateLimiting APIs - #61788
Conversation
ghost
commented
Nov 18, 2021
Note regarding the This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, to please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change. |
ghost
commented
Nov 18, 2021
Tagging subscribers to this area: @mangod9 Issue DetailsPart of dotnet/aspnetcore#37385 There were a couple minor code fixups needed for building in the repo because the project now targets more TFMs than just netstandard2.0. I will call out the changes in code review comments. Couple things to note:
|
There was a problem hiding this comment.
Added = default; since the compiler doesn't like you using non-initialized variables.
There was a problem hiding this comment.
Added ! to obj, to fix nullable warning
There was a problem hiding this comment.
The use of cancellationToken in the delegate is causing this method to always allocate a closure, even on the fast paths.
There was a problem hiding this comment.
Added ? since IEquatable requires it, and added the if (other is null) check
There was a problem hiding this comment.
Same issue here with regards to a closure.
There was a problem hiding this comment.
Changed to private and use reflection in tests to avoid IVT
There was a problem hiding this comment.
Changed to reflection to call private method instead of IVT
There was a problem hiding this comment.
These non-synchronized fast-path checks mean we might return failure even if success is possible. That's ok?
There was a problem hiding this comment.
I think it's fine, it's an implicit race, locking would still race with someone releasing permits at the same time.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The approved API called these:
ProcessOldest,
ProcessNewest
There was a problem hiding this comment.
The approved API code was wrong, the comment above the code states:
We decided to rename the QueueProcessingOrder members from { ProcessOldest, ProcessNewest } to { OldestFirst, NewestFirst }
There was a problem hiding this comment.
Shouldn't metadata be attributed with [MaybeNullWhen(false)]?
What does it mean to return true from TryGetMetadata, but the metadata still being null?
There was a problem hiding this comment.
During one of the reviews it was discussed that a null value could be valid metadata
There was a problem hiding this comment.
I remember discussing wanting to distinguish between metadata that is sometimes defined but not present (returns true but gives null) vs metadata that is never present (returns false).
Previous discussion: #52079 (comment)
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
This description is different than ConcurrencyLimiterOptions:
/// Maximum number of permits that can be queued concurrently.
There was a problem hiding this comment.
This is done on purpose. The API review called out that TokenBucket should refer to permits as tokens where possible.
There was a problem hiding this comment.
Is it odd that we have RateLimiter, TokenBucketRateLimiter, but then ConcurrencyLimiter? Why not ConcurrencyRateLimiter?
martincostello
left a comment
There was a problem hiding this comment.
We've had a rate-limiting prototype sitting around in Polly for a while (App-vNext/Polly#666) so I thought I'd take a look at this - looks nice.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
2010f64 to
f59ff02CompareUh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
| } | ||
| // Return SuccessfulLease or FailedLease to indicate limiter state | ||
| if (permitCount == 0 && !_disposed) |
There was a problem hiding this comment.
Do we want to throw ObjectDisposedException if this has been disposed?
There was a problem hiding this comment.
Should an ODE throw synchronously or be wrapped in a ValueTask?
There was a problem hiding this comment.
I guess the first question is:
- Do we want to throw ODE or always return "failed" when a limiter is disposed?
Doing a quick check of other System.Threading disposable types, they seem to throw ODE: Barrier, ManualResetEventSlim, ReaderWriterLockSlim
For the next question, I would say it is similar to argument checking - so we would throw inline.
Part of dotnet/aspnetcore#37385
Moves the current non-generic APIs and two rate limiter implementations from https://github.com/aspnet/AspLabs/tree/main/src/RateLimiting.
There were a couple minor code fixups needed for building in the repo because the project now targets more TFMs than just netstandard2.0. I will call out the changes in code review comments.
Couple things to note:
TaskExtensions.DefaultTimeout()methods from asplabs/aspnetcore that we use in our tests to detect hangs/prevent hangs on the CI. Not sure how the Runtime handles test hangs as I haven't seen tests do anything special with awaiting tasks.<IsPackable>or any other metadata?