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();
}
}
}
}