mirror of
https://github.com/JKorf/CryptoExchange.Net.git
synced 2026-08-20 04:42:57 +00:00
Initial commit
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
namespace CryptoExchange.Net.RateLimiter
|
||||
{
|
||||
public interface IRateLimiter
|
||||
{
|
||||
double LimitRequest(string url);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace CryptoExchange.Net.RateLimiter
|
||||
{
|
||||
public class RateLimitObject
|
||||
{
|
||||
public object LockObject { get; }
|
||||
private List<DateTime> Times { get; }
|
||||
|
||||
public RateLimitObject()
|
||||
{
|
||||
LockObject = new object();
|
||||
Times = new List<DateTime>();
|
||||
}
|
||||
|
||||
public double GetWaitTime(DateTime time, int limit, TimeSpan perTimePeriod)
|
||||
{
|
||||
Times.RemoveAll(d => d < time - perTimePeriod);
|
||||
if (Times.Count >= limit)
|
||||
return (Times.First() - (time - perTimePeriod)).TotalMilliseconds;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void Add(DateTime time)
|
||||
{
|
||||
Times.Add(time);
|
||||
Times.Sort();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
|
||||
namespace CryptoExchange.Net.RateLimiter
|
||||
{
|
||||
/// <summary>
|
||||
/// Limits the amount of requests per time period to a certain limit, counts the request per endpoint.
|
||||
/// </summary>
|
||||
public class RateLimiterPerEndpoint: IRateLimiter
|
||||
{
|
||||
internal Dictionary<string, RateLimitObject> history = new Dictionary<string, RateLimitObject>();
|
||||
|
||||
private int limitPerEndpoint;
|
||||
private TimeSpan perTimePeriod;
|
||||
private object historyLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Create a new RateLimiterPerEndpoint. This rate limiter limits the amount of requests per time period to a certain limit, counts the request per endpoint.
|
||||
/// </summary>
|
||||
/// <param name="limitPerEndpoint">The amount to limit to</param>
|
||||
/// <param name="perTimePeriod">The time period over which the limit counts</param>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
namespace CryptoExchange.Net.RateLimiter
|
||||
{
|
||||
/// <summary>
|
||||
/// Limits the amount of requests per time period to a certain limit, counts the total amount of requests.
|
||||
/// </summary>
|
||||
public class RateLimiterTotal: IRateLimiter
|
||||
{
|
||||
internal List<DateTime> history = new List<DateTime>();
|
||||
|
||||
private int limit;
|
||||
private TimeSpan perTimePeriod;
|
||||
private object requestLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="limit">The amount to limit to</param>
|
||||
/// <param name="perTimePeriod">The time period over which the limit counts</param>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user