mirror of
https://github.com/JKorf/CryptoExchange.Net
synced 2025-06-08 16:36:15 +00:00
Merge pull request #75 from burakoner/master
Rate Limiter Credits parameter to SendRequest method
This commit is contained in:
commit
edbca6a680
@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.Interfaces
|
namespace CryptoExchange.Net.Interfaces
|
||||||
{
|
{
|
||||||
@ -13,7 +13,8 @@ namespace CryptoExchange.Net.Interfaces
|
|||||||
/// <param name="client"></param>
|
/// <param name="client"></param>
|
||||||
/// <param name="url"></param>
|
/// <param name="url"></param>
|
||||||
/// <param name="limitBehaviour"></param>
|
/// <param name="limitBehaviour"></param>
|
||||||
|
/// <param name="credits"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
CallResult<double> LimitRequest(RestClient client, string url, RateLimitingBehaviour limitBehaviour);
|
CallResult<double> LimitRequest(RestClient client, string url, RateLimitingBehaviour limitBehaviour, int credits=1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ namespace CryptoExchange.Net.RateLimiter
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public CallResult<double> LimitRequest(RestClient client, string url, RateLimitingBehaviour limitBehaviour)
|
public CallResult<double> LimitRequest(RestClient client, string url, RateLimitingBehaviour limitBehaviour, int credits = 1)
|
||||||
{
|
{
|
||||||
if(client.authProvider?.Credentials?.Key == null)
|
if(client.authProvider?.Credentials?.Key == null)
|
||||||
return new CallResult<double>(0, null);
|
return new CallResult<double>(0, null);
|
||||||
|
65
CryptoExchange.Net/RateLimiter/RateLimiterCredit.cs
Normal file
65
CryptoExchange.Net/RateLimiter/RateLimiterCredit.cs
Normal file
@ -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
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Limits the amount of requests per time period to a certain limit, counts the total amount of requests.
|
||||||
|
/// </summary>
|
||||||
|
public class RateLimiterCredit : IRateLimiter
|
||||||
|
{
|
||||||
|
internal List<DateTime> history = new List<DateTime>();
|
||||||
|
|
||||||
|
private readonly int limit;
|
||||||
|
private readonly TimeSpan perTimePeriod;
|
||||||
|
private readonly 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 RateLimiterCredit(int limit, TimeSpan perTimePeriod)
|
||||||
|
{
|
||||||
|
this.limit = limit;
|
||||||
|
this.perTimePeriod = perTimePeriod;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public CallResult<double> 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<double>(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<double>(waitTime, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -30,7 +30,7 @@ namespace CryptoExchange.Net.RateLimiter
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public CallResult<double> LimitRequest(RestClient client, string url, RateLimitingBehaviour limitingBehaviour)
|
public CallResult<double> LimitRequest(RestClient client, string url, RateLimitingBehaviour limitingBehaviour, int credits = 1)
|
||||||
{
|
{
|
||||||
int waitTime;
|
int waitTime;
|
||||||
RateLimitObject rlo;
|
RateLimitObject rlo;
|
||||||
|
@ -31,7 +31,7 @@ namespace CryptoExchange.Net.RateLimiter
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public CallResult<double> LimitRequest(RestClient client, string url, RateLimitingBehaviour limitBehaviour)
|
public CallResult<double> LimitRequest(RestClient client, string url, RateLimitingBehaviour limitBehaviour, int credits = 1)
|
||||||
{
|
{
|
||||||
var sw = Stopwatch.StartNew();
|
var sw = Stopwatch.StartNew();
|
||||||
lock (requestLock)
|
lock (requestLock)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
@ -172,7 +172,7 @@ namespace CryptoExchange.Net
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[return: NotNull]
|
[return: NotNull]
|
||||||
protected virtual async Task<WebCallResult<T>> SendRequest<T>(Uri uri, HttpMethod method, CancellationToken cancellationToken,
|
protected virtual async Task<WebCallResult<T>> SendRequest<T>(Uri uri, HttpMethod method, CancellationToken cancellationToken,
|
||||||
Dictionary<string, object>? parameters = null, bool signed = false, bool checkResult = true, PostParameters? postPosition = null, ArrayParametersSerialization? arraySerialization = null) where T : class
|
Dictionary<string, object>? parameters = null, bool signed = false, bool checkResult = true, PostParameters? postPosition = null, ArrayParametersSerialization? arraySerialization = null, int credits=1) where T : class
|
||||||
{
|
{
|
||||||
var requestId = NextId();
|
var requestId = NextId();
|
||||||
log.Write(LogVerbosity.Debug, $"[{requestId}] Creating request for " + uri);
|
log.Write(LogVerbosity.Debug, $"[{requestId}] Creating request for " + uri);
|
||||||
@ -185,7 +185,7 @@ namespace CryptoExchange.Net
|
|||||||
var request = ConstructRequest(uri, method, parameters, signed, postPosition ?? postParametersPosition, arraySerialization ?? this.arraySerialization, requestId);
|
var request = ConstructRequest(uri, method, parameters, signed, postPosition ?? postParametersPosition, arraySerialization ?? this.arraySerialization, requestId);
|
||||||
foreach (var limiter in RateLimiters)
|
foreach (var limiter in RateLimiters)
|
||||||
{
|
{
|
||||||
var limitResult = limiter.LimitRequest(this, uri.AbsolutePath, RateLimitBehaviour);
|
var limitResult = limiter.LimitRequest(this, uri.AbsolutePath, RateLimitBehaviour, credits);
|
||||||
if (!limitResult.Success)
|
if (!limitResult.Success)
|
||||||
{
|
{
|
||||||
log.Write(LogVerbosity.Debug, $"[{requestId}] Request {uri.AbsolutePath} failed because of rate limit");
|
log.Write(LogVerbosity.Debug, $"[{requestId}] Request {uri.AbsolutePath} failed because of rate limit");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user