52 lines
1.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Infra
{
public class RateLimiter
{
private readonly int _maxRequests;
private readonly TimeSpan _interval;
private int _requestCount;
private DateTime _windowStart;
private readonly object _lock = new();
public RateLimiter(int maxRequests, TimeSpan interval)
{
_maxRequests = maxRequests;
_interval = interval;
var now = DateTime.Now;
_windowStart = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute - (now.Minute % interval.Minutes), 0);
_requestCount = 0;
}
public async Task WaitAsync(CancellationToken ct)
{
while (true)
{
lock (_lock)
{
if ((DateTime.Now - _windowStart) > _interval)
{
// reset janela
_windowStart = DateTime.Now;
_requestCount = 0;
}
if (_requestCount < _maxRequests)
{
_requestCount++;
return; // pode prosseguir
}
}
// já bateu o limite → espera até reset
await Task.Delay(200, ct); // aguarda 200ms e tenta de novo
}
}
}
}