using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; namespace CryptoExchange.Net.RateLimiter { /// /// Limits the amount of requests per time period to a certain limit, counts the total amount of requests. /// public class RateLimiterTotal: IRateLimiter { internal List history = new List(); private readonly int limit; private readonly TimeSpan perTimePeriod; private readonly object requestLock = new object(); /// /// Create a new RateLimiterTotal. This rate limiter limits the amount of requests per time period to a certain limit, counts the total amount of requests. /// /// The amount to limit to /// The time period over which the limit counts public RateLimiterTotal(int limit, TimeSpan perTimePeriod) { this.limit = limit; this.perTimePeriod = perTimePeriod; } public double LimitRequest(string url) { var sw = Stopwatch.StartNew(); lock (requestLock) { sw.Stop(); double waitTime = 0; var checkTime = DateTime.UtcNow; history.RemoveAll(d => d < checkTime - perTimePeriod); if (history.Count >= limit) { waitTime = (history.First() - (checkTime - perTimePeriod)).TotalMilliseconds; if (waitTime > 0) { Thread.Sleep(Convert.ToInt32(waitTime)); waitTime += sw.ElapsedMilliseconds; } } history.Add(DateTime.UtcNow); history.Sort(); return waitTime; } } } }