using System.Collections.Concurrent; namespace GermanApp.Infrastructure.Services; /// /// Simple in-memory rate limiter for Mistral API requests. /// This is part of the Infrastructure layer. /// public class MistralRateLimiter { private readonly int _maxRequests; private readonly TimeSpan _window; private readonly ConcurrentDictionary> _requests = new(); /// /// Creates a new rate limiter. /// /// Maximum requests allowed per minute public MistralRateLimiter(int maxRequestsPerMinute) { _maxRequests = maxRequestsPerMinute; _window = TimeSpan.FromMinutes(1); } /// /// Attempts to acquire a rate limit token for the specified endpoint. /// /// The API endpoint being called /// True if request is allowed, false if rate limit exceeded public bool TryAcquire(string endpoint) { var now = DateTime.UtcNow; var requests = _requests.GetOrAdd(endpoint, _ => new List()); lock (requests) { // Remove old requests outside the window requests.RemoveAll(r => now - r > _window); // Check if limit exceeded if (requests.Count >= _maxRequests) return false; // Add new request requests.Add(now); return true; } } /// /// Gets the current request count for an endpoint. /// /// The API endpoint /// Number of requests in the current window public int GetCurrentCount(string endpoint) { if (_requests.TryGetValue(endpoint, out var requests)) { lock (requests) { var now = DateTime.UtcNow; requests.RemoveAll(r => now - r > _window); return requests.Count; } } return 0; } /// /// Resets the rate limiter for a specific endpoint. /// /// The API endpoint public void Reset(string endpoint) { if (_requests.TryGetValue(endpoint, out var requests)) { lock (requests) { requests.Clear(); } } } /// /// Resets all rate limiters. /// public void ResetAll() { foreach (var kvp in _requests) { lock (kvp.Value) { kvp.Value.Clear(); } } } }