From 36a03587b93fe658d4a7a15af1c213171b91d13e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20=C3=96ner?= Date: Wed, 6 Jan 2021 00:29:25 +0300 Subject: [PATCH] Create RateLimiterCredit.cs --- .../RateLimiter/RateLimiterCredit.cs | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 CryptoExchange.Net/RateLimiter/RateLimiterCredit.cs diff --git a/CryptoExchange.Net/RateLimiter/RateLimiterCredit.cs b/CryptoExchange.Net/RateLimiter/RateLimiterCredit.cs new file mode 100644 index 0000000..ef6cc2b --- /dev/null +++ b/CryptoExchange.Net/RateLimiter/RateLimiterCredit.cs @@ -0,0 +1,65 @@ +using CryptoExchange.Net.Interfaces; +using CryptoExchange.Net.Objects; +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 RateLimiterCredit : 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 RateLimiterCredit(int limit, TimeSpan perTimePeriod) + { + this.limit = limit; + this.perTimePeriod = perTimePeriod; + } + + /// + public CallResult LimitRequest(RestClient client, string url, RateLimitingBehaviour limitBehaviour, int credits = 1) + { + 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) + { + if (limitBehaviour == RateLimitingBehaviour.Fail) + return new CallResult(waitTime, new RateLimitError($"total limit of {limit} reached")); + + Thread.Sleep(Convert.ToInt32(waitTime)); + waitTime += sw.ElapsedMilliseconds; + } + } + + for (int i = 1; i <= credits; i++) + history.Add(DateTime.UtcNow); + + history.Sort(); + return new CallResult(waitTime, null); + } + } + } +}