| 1234567891011121314151617181920212223242526272829303132333435363738394041 |
- using System.Collections.Concurrent;
- namespace molilian.core
- {
- public static class SpecialBusinessRateLimiter
- {
- private static readonly ConcurrentDictionary<string, SlidingWindowState> States = new();
- public static bool TryAcquire(string bucketKey, int limit, TimeSpan window)
- {
- if (string.IsNullOrWhiteSpace(bucketKey)) return true;
- if (limit <= 0 || window <= TimeSpan.Zero) return true;
- var state = States.GetOrAdd(bucketKey, _ => new SlidingWindowState());
- var nowTicks = DateTime.UtcNow.Ticks;
- var minTicks = nowTicks - window.Ticks;
- lock (state.SyncRoot)
- {
- while (state.Timestamps.Count > 0 && state.Timestamps.Peek() < minTicks)
- {
- state.Timestamps.Dequeue();
- }
- if (state.Timestamps.Count >= limit)
- {
- return false;
- }
- state.Timestamps.Enqueue(nowTicks);
- return true;
- }
- }
- private sealed class SlidingWindowState
- {
- public object SyncRoot { get; } = new();
- public Queue<long> Timestamps { get; } = new();
- }
- }
- }
|