using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading; namespace CryptoExchange.Net.RateLimiter { /// /// Limits the amount of requests per time period to a certain limit, counts the request per endpoint. /// public class RateLimiterPerEndpoint: IRateLimiter { internal Dictionary history = new Dictionary(); private int limitPerEndpoint; private TimeSpan perTimePeriod; private object historyLock = new object(); /// /// Create a new RateLimiterPerEndpoint. This rate limiter limits the amount of requests per time period to a certain limit, counts the request per endpoint. /// /// The amount to limit to /// The time period over which the limit counts public RateLimiterPerEndpoint(int limitPerEndpoint, TimeSpan perTimePeriod) { this.limitPerEndpoint = limitPerEndpoint; this.perTimePeriod = perTimePeriod; } public double LimitRequest(string url) { double waitTime; RateLimitObject rlo; lock (historyLock) { if (history.ContainsKey(url)) rlo = history[url]; else { rlo = new RateLimitObject(); history.Add(url, rlo); } } var sw = Stopwatch.StartNew(); lock (rlo.LockObject) { sw.Stop(); waitTime = rlo.GetWaitTime(DateTime.UtcNow, limitPerEndpoint, perTimePeriod); if (waitTime != 0) { Thread.Sleep(Convert.ToInt32(waitTime)); waitTime += sw.ElapsedMilliseconds; } rlo.Add(DateTime.UtcNow); } return waitTime; } } }