Skip to content

Fix NoopLimiter disposal in DefaultPartitionedRateLimiter Heartbeat#127582

Open
Copilot wants to merge 18 commits into
mainfrom
copilot/fix-noop-limiter-disposal
Open

Fix NoopLimiter disposal in DefaultPartitionedRateLimiter Heartbeat#127582
Copilot wants to merge 18 commits into
mainfrom
copilot/fix-noop-limiter-disposal

Conversation

Copilot AI commented Apr 29, 2026

Copy link
Copy Markdown
Contributor

Fixes DefaultPartitionedRateLimiter so that NoopLimiter partitions are evicted and disposed by the Heartbeat timer, which previously never happened because NoopLimiter.IdleDuration always returns null.

Changes Made

  • Introduced a LimiterEntry wrapper that tracks a LastAccessTimestamp (updated on each Acquire/WaitAsync call) alongside the RateLimiter instance.
  • Added GetIdleDuration(LimiterEntry) helper that falls back to the elapsed time since last access for NoopLimiter (whose IdleDuration is always null), and returns null for all other limiter types that return null (preserving the existing "do not evict" contract).
  • Updated the Heartbeat eviction check to use the is TimeSpan idleDuration && idleDuration > s_idleTimeLimit pattern (with ?? TimeSpan.Zero for the under-lock re-check), correctly handling the nullable TimeSpan? return — null skips eviction, matching the original pattern.
  • Used Volatile.Read/Volatile.Write for atomic 64-bit timestamp access on 32-bit platforms.
  • Added a RateLimiterHelper.GetElapsedTime(long) overload to avoid .GetValueOrDefault() at call sites.
  • Added tests covering NoopLimiter eviction via Heartbeat and verifying that non-NoopLimiter partitions with IdleDuration == null are not evicted while active.

Copilot AI requested review from Copilot and removed request for Copilot April 29, 2026 20:47
Copilot AI linked an issue Apr 29, 2026 that may be closed by this pull request
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @VSadov
See info in area-owners.md if you want to be subscribed.

Copilot AI requested review from Copilot and removed request for Copilot April 29, 2026 21:12
Copilot AI changed the title [WIP] Fix DefaultPartitionedRateLimiter to dispose NoopLimiter Evict idle partitions whose IdleDuration is always null Apr 29, 2026
Copilot AI requested a review from VSadov April 29, 2026 21:18
Copilot AI requested review from Copilot and removed request for Copilot June 14, 2026 18:31
Copilot AI changed the title Add type-instance assertion before reflection GetValue in rate limiter test helper Fix NoopLimiter partition eviction in DefaultPartitionedRateLimiter Jun 14, 2026
Copilot AI requested review from Copilot and removed request for Copilot June 14, 2026 18:31

@eduardo-vp eduardo-vp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@VSadov

VSadov commented Jun 16, 2026

Copy link
Copy Markdown
Member

Thanks!

Copilot AI and others added 17 commits June 16, 2026 22:02
… atomic 64-bit access

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/7cfc3a4e-ebbd-4056-97a5-69edc299af17

Co-authored-by: VSadov <8218165+VSadov@users.noreply.github.com>
Co-authored-by: VSadov <8218165+VSadov@users.noreply.github.com>
Co-authored-by: VSadov <8218165+VSadov@users.noreply.github.com>
Merges current main into the PR and updates the two new test methods (NoopLimiterPartitionIsCleanedUp and LimiterWithNullIdleDurationIsNotCleanedUp) to:
- Pass explicit type arguments to Utils.RunTimerFunc<TResource, TKey> (signature changed in main).
- Use the trim-safe Type.GetType + MakeGenericType pattern in the reflection helpers (BackdateLastAccessTimestamp / GetLimiterEntry / GetLazyLimiterEntry) now that the tests project no longer disables the trim analyzer.

All 344 tests pass; net11.0 and net481 build with 0 warnings.

Co-authored-by: VSadov <8218165+VSadov@users.noreply.github.com>
Co-authored-by: VSadov <8218165+VSadov@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: VSadov <8218165+VSadov@users.noreply.github.com>
Co-authored-by: VSadov <8218165+VSadov@users.noreply.github.com>
…e in GetLazyLimiterEntry

Co-authored-by: VSadov <8218165+VSadov@users.noreply.github.com>
Co-authored-by: VSadov <8218165+VSadov@users.noreply.github.com>
Co-authored-by: VSadov <8218165+VSadov@users.noreply.github.com>
Co-authored-by: VSadov <8218165+VSadov@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

Comment on lines +13 to +15
private const string DefaultPartitionedRateLimiterTypeName = "System.Threading.RateLimiting.DefaultPartitionedRateLimiter`2, System.Threading.RateLimiting";
private const string DefaultPartitionedRateLimiterEntryTypeName = "System.Threading.RateLimiting.DefaultPartitionedRateLimiter`2+LimiterEntry, System.Threading.RateLimiting";

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DefaultPartitionedRateLimiter never disposes NoopLimiter

5 participants