mirror of
				https://github.com/Kareadita/Kavita.git
				synced 2025-10-31 10:37:04 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			60 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			60 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Collections.Generic;
 | |
| 
 | |
| namespace API.Helpers;
 | |
| 
 | |
| public class RateLimiter(int maxRequests, TimeSpan duration, bool refillBetween = true)
 | |
| {
 | |
|     private readonly Dictionary<string, (int Tokens, DateTime LastRefill)> _tokenBuckets = new();
 | |
|     private readonly object _lock = new();
 | |
| 
 | |
|     public bool TryAcquire(string key)
 | |
|     {
 | |
|         lock (_lock)
 | |
|         {
 | |
|             if (!_tokenBuckets.TryGetValue(key, out var bucket))
 | |
|             {
 | |
|                 bucket = (Tokens: maxRequests, LastRefill: DateTime.UtcNow);
 | |
|                 _tokenBuckets[key] = bucket;
 | |
|             }
 | |
| 
 | |
|             RefillTokens(key);
 | |
| 
 | |
|             lock (_lock)
 | |
|             {
 | |
| 
 | |
|                 if (_tokenBuckets[key].Tokens > 0)
 | |
|                 {
 | |
|                     _tokenBuckets[key] = (Tokens: _tokenBuckets[key].Tokens - 1, LastRefill: _tokenBuckets[key].LastRefill);
 | |
|                     return true;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             return false;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     private void RefillTokens(string key)
 | |
|     {
 | |
|         lock (_lock)
 | |
|         {
 | |
|             var now = DateTime.UtcNow;
 | |
|             var timeSinceLastRefill = now - _tokenBuckets[key].LastRefill;
 | |
|             var tokensToAdd = (int) (timeSinceLastRefill.TotalSeconds / duration.TotalSeconds);
 | |
| 
 | |
|             // Refill the bucket if the elapsed time is greater than or equal to the duration
 | |
|             if (timeSinceLastRefill >= duration)
 | |
|             {
 | |
|                 _tokenBuckets[key] = (Tokens: maxRequests, LastRefill: now);
 | |
|                 Console.WriteLine($"Tokens Refilled to Max: {maxRequests}");
 | |
|             }
 | |
|             else if (tokensToAdd > 0 && refillBetween)
 | |
|             {
 | |
|                 _tokenBuckets[key] = (Tokens: Math.Min(maxRequests, _tokenBuckets[key].Tokens + tokensToAdd), LastRefill: now);
 | |
|                 Console.WriteLine($"Tokens Refilled: {_tokenBuckets[key].Tokens}");
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 |