// Archivo: Elecciones.Infrastructure/Services/RateLimiterService.cs using System.Threading; using System.Threading.Tasks; namespace Elecciones.Infrastructure.Services; public class RateLimiterService { private readonly SemaphoreSlim _semaphore; private readonly int _limit; private readonly TimeSpan _period; private Timer _timer; public RateLimiterService(int limit, TimeSpan period) { _limit = limit; _period = period; _semaphore = new SemaphoreSlim(limit, limit); // Un temporizador que "rellena el cubo" cada 5 minutos. _timer = new Timer( callback: _ => RefillBucket(), state: null, dueTime: period, period: period); } private void RefillBucket() { // Calcula cuántas fichas faltan en el cubo. var releaseCount = _limit - _semaphore.CurrentCount; if (releaseCount > 0) { // Añade las fichas que faltan. _semaphore.Release(releaseCount); } } // El método que usarán nuestras tareas para "pedir una ficha". public async Task WaitAsync(CancellationToken cancellationToken = default) { await _semaphore.WaitAsync(cancellationToken); } }