1
0
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:
JKorf
2018-02-28 13:53:29 +01:00
parent e2af98f2c9
commit 2bf860947a
23 changed files with 837 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
namespace CryptoExchange.Net.RateLimiter
{
public interface IRateLimiter
{
double LimitRequest(string url);
}
}
+32
View File
@@ -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();
}
}
}
+62
View File
@@ -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;
}
}
}
+57
View File
@@ -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;
}
}
}
}