mirror of
https://github.com/JKorf/CryptoExchange.Net.git
synced 2026-10-13 22:51:39 +00:00
Added WithRateLimitAdmissionAsync for REST and Socket clients
This commit is contained in:
@@ -1,10 +1,13 @@
|
|||||||
using System;
|
|
||||||
using CryptoExchange.Net.Interfaces.Clients;
|
using CryptoExchange.Net.Interfaces.Clients;
|
||||||
using CryptoExchange.Net.Objects.Errors;
|
using CryptoExchange.Net.Objects.Errors;
|
||||||
using CryptoExchange.Net.Objects.Options;
|
using CryptoExchange.Net.Objects.Options;
|
||||||
|
using CryptoExchange.Net.RateLimiting;
|
||||||
using CryptoExchange.Net.SharedApis;
|
using CryptoExchange.Net.SharedApis;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Logging.Abstractions;
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.Clients
|
namespace CryptoExchange.Net.Clients
|
||||||
{
|
{
|
||||||
@@ -78,6 +81,11 @@ namespace CryptoExchange.Net.Clients
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected internal virtual ErrorMapping ErrorMapping { get; } = new ErrorMapping([]);
|
protected internal virtual ErrorMapping ErrorMapping { get; } = new ErrorMapping([]);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Current rate limit admission override
|
||||||
|
/// </summary>
|
||||||
|
protected readonly AsyncLocal<RateLimitAdmission?> AdmissionOverride = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -122,6 +130,29 @@ namespace CryptoExchange.Net.Clients
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ErrorInfo GetErrorInfo(string code, string? message = null) => ErrorMapping.GetErrorInfo(code.ToString(), message);
|
public ErrorInfo GetErrorInfo(string code, string? message = null) => ErrorMapping.GetErrorInfo(code.ToString(), message);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task<TResult> WithRateLimitAdmissionAsync<TResult>(
|
||||||
|
RateLimitAdmission admission,
|
||||||
|
Func<Task<TResult>> operation)
|
||||||
|
{
|
||||||
|
if (admission == null)
|
||||||
|
throw new ArgumentNullException(nameof(admission));
|
||||||
|
if (operation == null)
|
||||||
|
throw new ArgumentNullException(nameof(operation));
|
||||||
|
|
||||||
|
var previous = AdmissionOverride.Value;
|
||||||
|
AdmissionOverride.Value = admission;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await operation().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AdmissionOverride.Value = previous;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Dispose
|
/// Dispose
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -350,9 +350,8 @@ namespace CryptoExchange.Net.Clients
|
|||||||
|
|
||||||
if (ClientOptions.RateLimiterEnabled)
|
if (ClientOptions.RateLimiterEnabled)
|
||||||
{
|
{
|
||||||
var rateRatio = 1.0;
|
var admissionOverride = AdmissionOverride.Value ?? ClientOptions.RateLimitAdmission?.Invoke(definition, requestWeight);
|
||||||
if (ClientOptions.RateLimitAdmission != null)
|
var rateRatio = admissionOverride?.MaxUtilizationRatio ?? 1.0;
|
||||||
rateRatio = ClientOptions.RateLimitAdmission(definition, requestWeight).MaxUtilization;
|
|
||||||
|
|
||||||
var limitResult = await definition.RateLimitGate.ProcessAsync(
|
var limitResult = await definition.RateLimitGate.ProcessAsync(
|
||||||
_logger,
|
_logger,
|
||||||
@@ -379,9 +378,8 @@ namespace CryptoExchange.Net.Clients
|
|||||||
if (ClientOptions.RateLimiterEnabled)
|
if (ClientOptions.RateLimiterEnabled)
|
||||||
{
|
{
|
||||||
var singleRequestWeight = weightSingleLimiter ?? 1;
|
var singleRequestWeight = weightSingleLimiter ?? 1;
|
||||||
var rateRatio = 1.0;
|
var admissionOverride = AdmissionOverride.Value ?? ClientOptions.RateLimitAdmission?.Invoke(definition, singleRequestWeight);
|
||||||
if (ClientOptions.RateLimitAdmission != null)
|
var rateRatio = admissionOverride?.MaxUtilizationRatio ?? 1.0;
|
||||||
rateRatio = ClientOptions.RateLimitAdmission(definition, singleRequestWeight).MaxUtilization;
|
|
||||||
|
|
||||||
var limitResult = await definition.RateLimitGate.ProcessSingleAsync(
|
var limitResult = await definition.RateLimitGate.ProcessSingleAsync(
|
||||||
_logger,
|
_logger,
|
||||||
|
|||||||
@@ -858,7 +858,8 @@ namespace CryptoExchange.Net.Clients
|
|||||||
ReconnectInterval = ClientOptions.ReconnectInterval,
|
ReconnectInterval = ClientOptions.ReconnectInterval,
|
||||||
RateLimiter = ClientOptions.RateLimiterEnabled ? RateLimiter : null,
|
RateLimiter = ClientOptions.RateLimiterEnabled ? RateLimiter : null,
|
||||||
RateLimitingBehavior = ClientOptions.RateLimitingBehaviour,
|
RateLimitingBehavior = ClientOptions.RateLimitingBehaviour,
|
||||||
RateLimitAdmission = ClientOptions.RateLimitAdmission,
|
RateLimitAdmissionCallbackOptions = (def, weight) => ClientOptions.RateLimitAdmission?.Invoke(def, weight),
|
||||||
|
RateLimitAdmissionCallbackRequest = () => AdmissionOverride.Value,
|
||||||
Proxy = ClientOptions.Proxy,
|
Proxy = ClientOptions.Proxy,
|
||||||
Timeout = ApiOptions.SocketNoDataTimeout ?? ClientOptions.SocketNoDataTimeout,
|
Timeout = ApiOptions.SocketNoDataTimeout ?? ClientOptions.SocketNoDataTimeout,
|
||||||
ReceiveBufferSize = ClientOptions.ReceiveBufferSize,
|
ReceiveBufferSize = ClientOptions.ReceiveBufferSize,
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
using CryptoExchange.Net.Interfaces;
|
using CryptoExchange.Net.Clients;
|
||||||
|
using CryptoExchange.Net.Interfaces;
|
||||||
|
using CryptoExchange.Net.Interfaces.Clients;
|
||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
|
using CryptoExchange.Net.RateLimiting;
|
||||||
using CryptoExchange.Net.SharedApis;
|
using CryptoExchange.Net.SharedApis;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using System;
|
using System;
|
||||||
@@ -11,6 +14,7 @@ using System.IO.Compression;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
|
|
||||||
namespace CryptoExchange.Net
|
namespace CryptoExchange.Net
|
||||||
@@ -510,6 +514,23 @@ namespace CryptoExchange.Net
|
|||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Execute an operation with a specific rate limit admission rule
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="client">Client</param>
|
||||||
|
/// <param name="admission">Rate limit admission rule</param>
|
||||||
|
/// <param name="operation">Operation to execute</param>
|
||||||
|
public static Task<TResult> WithRateLimitAdmissionAsync<TClient, TResult>(
|
||||||
|
this TClient client,
|
||||||
|
RateLimitAdmission admission,
|
||||||
|
Func<TClient, Task<TResult>> operation)
|
||||||
|
where TClient : IRateLimitAdmissionClient
|
||||||
|
{
|
||||||
|
return client.WithRateLimitAdmissionAsync(
|
||||||
|
admission,
|
||||||
|
() => operation(client));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using CryptoExchange.Net.Authentication;
|
using CryptoExchange.Net.SharedApis;
|
||||||
using CryptoExchange.Net.Objects.Options;
|
|
||||||
using CryptoExchange.Net.SharedApis;
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.Interfaces.Clients
|
namespace CryptoExchange.Net.Interfaces.Clients
|
||||||
@@ -8,7 +6,7 @@ namespace CryptoExchange.Net.Interfaces.Clients
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Base api client
|
/// Base api client
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IBaseApiClient
|
public interface IBaseApiClient : IRateLimitAdmissionClient
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Exchange name
|
/// Exchange name
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
using CryptoExchange.Net.RateLimiting;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.Interfaces
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A client supporting rate limit admission rules
|
||||||
|
/// </summary>
|
||||||
|
public interface IRateLimitAdmissionClient
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Execute an operation with a specific rate limit admission rule
|
||||||
|
/// </summary>
|
||||||
|
Task<TResult> WithRateLimitAdmissionAsync<TResult>(
|
||||||
|
RateLimitAdmission admission,
|
||||||
|
Func<Task<TResult>> operation);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -69,7 +69,12 @@ namespace CryptoExchange.Net.Objects.Sockets
|
|||||||
/// A delegate receiving the request definition and the request weight that can be used to determine whether a request should be admitted or rejected based
|
/// A delegate receiving the request definition and the request weight that can be used to determine whether a request should be admitted or rejected based
|
||||||
/// on the request definition and the current rate limit usage ratio. This allows for custom rate limiting logic to be implemented.
|
/// on the request definition and the current rate limit usage ratio. This allows for custom rate limiting logic to be implemented.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Func<RequestDefinition, int, RateLimitAdmission>? RateLimitAdmission { get; set; }
|
public Func<RequestDefinition, int, RateLimitAdmission?>? RateLimitAdmissionCallbackOptions { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A delegate for retrieving the current rate limit admission decision for a specific request. This allows for custom rate limiting logic to be implemented.
|
||||||
|
/// </summary>
|
||||||
|
public Func<RateLimitAdmission?>? RateLimitAdmissionCallbackRequest { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Encoding for sending/receiving data
|
/// Encoding for sending/receiving data
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace CryptoExchange.Net.RateLimiting.Guards
|
|||||||
public string Name => "EndpointLimitGuard";
|
public string Name => "EndpointLimitGuard";
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string Description => $"Limit requests to endpoint";
|
public string Description => _windowType == RateLimitWindowType.Decay ? $"Endpoint limit of {_limit} with a decay rate of {_decayRate}" : $"Limit of {_limit} per {_period}";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
|
|||||||
@@ -12,13 +12,13 @@ namespace CryptoExchange.Net.RateLimiting
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Value ratio between 0 and 1
|
/// Value ratio between 0 and 1
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public double MaxUtilization { get; }
|
public double MaxUtilizationRatio { get; }
|
||||||
|
|
||||||
private RateLimitAdmission(double maxUtilizationValue) {
|
private RateLimitAdmission(double maxUtilizationValue) {
|
||||||
if (maxUtilizationValue <= 0 || maxUtilizationValue > 1)
|
if (maxUtilizationValue <= 0 || maxUtilizationValue > 1)
|
||||||
throw new ArgumentOutOfRangeException(nameof(maxUtilizationValue), "Max utilization value must be bigger than 0 and less than or equal to 1");
|
throw new ArgumentOutOfRangeException(nameof(maxUtilizationValue), "Max utilization value must be bigger than 0 and less than or equal to 1");
|
||||||
|
|
||||||
MaxUtilization = maxUtilizationValue;
|
MaxUtilizationRatio = maxUtilizationValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -26,7 +26,7 @@ namespace CryptoExchange.Net.RateLimiting
|
|||||||
/// 1 means it's allowed to use the full rate limit.
|
/// 1 means it's allowed to use the full rate limit.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="value">0.5 means a max use 50% of the rate limit, 1 means the request is allowed to use the full rate limit</param>
|
/// <param name="value">0.5 means a max use 50% of the rate limit, 1 means the request is allowed to use the full rate limit</param>
|
||||||
public static RateLimitAdmission WithMaxUtilization(double value)
|
public static RateLimitAdmission WithMaxUtilizationRatio(double value)
|
||||||
=> new RateLimitAdmission(value);
|
=> new RateLimitAdmission(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,7 +131,10 @@ namespace CryptoExchange.Net.RateLimiting
|
|||||||
logger.RateLimitRequestFailed(itemId, definition.Path, guard.Name, guard.Description);
|
logger.RateLimitRequestFailed(itemId, definition.Path, guard.Name, guard.Description);
|
||||||
|
|
||||||
RateLimitTriggered?.Invoke(new RateLimitEvent(itemId, _name, guard.Description, definition, result.Current, requestWeight, result.Limit, result.Period, result.Delay, rateLimitingBehaviour));
|
RateLimitTriggered?.Invoke(new RateLimitEvent(itemId, _name, guard.Description, definition, result.Current, requestWeight, result.Limit, result.Period, result.Delay, rateLimitingBehaviour));
|
||||||
return CallResult.Fail(new ClientRateLimitError($"Rate limit check failed on guard {guard.Name}; {guard.Description}"));
|
var errorMsg = $"Rate limit check failed on guard {guard.Name}; {guard.Description}";
|
||||||
|
if (allowedRateRatio < 1)
|
||||||
|
errorMsg += $" with allowed ratio {allowedRateRatio}";
|
||||||
|
return CallResult.Fail(new ClientRateLimitError(errorMsg));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.Delay != TimeSpan.Zero)
|
if (result.Delay != TimeSpan.Zero)
|
||||||
@@ -139,7 +142,14 @@ namespace CryptoExchange.Net.RateLimiting
|
|||||||
// Delay is needed and limit behaviour is to wait for the request to be under the limit
|
// Delay is needed and limit behaviour is to wait for the request to be under the limit
|
||||||
_semaphore.Release();
|
_semaphore.Release();
|
||||||
|
|
||||||
var description = result.Limit == null ? guard.Description : $"{guard.Description}, Request weight: {requestWeight}, Current: {result.Current}, Limit: {result.Limit}, requests now being limited: {_waitingCount}";
|
var description =
|
||||||
|
result.Limit == null
|
||||||
|
? guard.Description
|
||||||
|
: $"{guard.Description}, Request weight: {requestWeight}," +
|
||||||
|
$" Current: {result.Current}" +
|
||||||
|
$", Limit: {result.Limit}" +
|
||||||
|
(allowedRateRatio < 1 ? $", Allowed ratio: {allowedRateRatio}" : "") +
|
||||||
|
$", requests now being limited: {_waitingCount}";
|
||||||
if (type == RateLimitItemType.Connection)
|
if (type == RateLimitItemType.Connection)
|
||||||
logger.RateLimitDelayingConnection(itemId, result.Delay, guard.Name, description);
|
logger.RateLimitDelayingConnection(itemId, result.Delay, guard.Name, description);
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
using CryptoExchange.Net.Clients;
|
using CryptoExchange.Net.Clients;
|
||||||
|
using CryptoExchange.Net.Interfaces.Clients;
|
||||||
|
using CryptoExchange.Net.RateLimiting;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
@@ -12,7 +15,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
{
|
{
|
||||||
private readonly Func<string, string, TradingMode, DateTime?, string> _symbolFormatter;
|
private readonly Func<string, string, TradingMode, DateTime?, string> _symbolFormatter;
|
||||||
private readonly Func<bool> _authDelegate;
|
private readonly Func<bool> _authDelegate;
|
||||||
|
private readonly IBaseApiClient _apiClient;
|
||||||
private IReadOnlyCollection<CapabilityOptions> _capabilities = Array.Empty<CapabilityOptions>();
|
private IReadOnlyCollection<CapabilityOptions> _capabilities = Array.Empty<CapabilityOptions>();
|
||||||
IReadOnlyCollection<CapabilityOptions> ISharedApi.Capabilities => _capabilities;
|
IReadOnlyCollection<CapabilityOptions> ISharedApi.Capabilities => _capabilities;
|
||||||
|
|
||||||
@@ -33,16 +36,17 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public SharedApiBase(
|
public SharedApiBase(
|
||||||
SharedTransport transport,
|
SharedTransport transport,
|
||||||
string exchange,
|
IBaseApiClient apiClient,
|
||||||
TradingMode[] supportedTradingModes,
|
TradingMode[] supportedTradingModes,
|
||||||
Func<bool> authenticated,
|
Func<bool> authenticated,
|
||||||
Func<string, string, TradingMode, DateTime?, string> formatSymbol)
|
Func<string, string, TradingMode, DateTime?, string> formatSymbol)
|
||||||
{
|
{
|
||||||
Transport = transport;
|
_apiClient = apiClient;
|
||||||
Exchange = exchange;
|
|
||||||
SupportedTradingModes = supportedTradingModes;
|
|
||||||
_authDelegate = authenticated;
|
_authDelegate = authenticated;
|
||||||
_symbolFormatter = formatSymbol;
|
_symbolFormatter = formatSymbol;
|
||||||
|
Transport = transport;
|
||||||
|
Exchange = apiClient.Exchange;
|
||||||
|
SupportedTradingModes = supportedTradingModes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -64,6 +68,12 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void ResetDefaultExchangeParameters() => ExchangeParameters.ResetStaticExchangeParameters(Exchange);
|
public void ResetDefaultExchangeParameters() => ExchangeParameters.ResetStaticExchangeParameters(Exchange);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task<TResult> WithRateLimitAdmissionAsync<TResult>(
|
||||||
|
RateLimitAdmission admission,
|
||||||
|
Func<Task<TResult>> operation)
|
||||||
|
=> _apiClient.WithRateLimitAdmissionAsync(admission, operation);
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public abstract SharedClientInfo Discover();
|
public abstract SharedClientInfo Discover();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
using System;
|
using CryptoExchange.Net.Interfaces;
|
||||||
|
using CryptoExchange.Net.RateLimiting;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Shared API
|
/// Shared API
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ISharedApi
|
public interface ISharedApi : IRateLimitAdmissionClient
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Name of the exchange
|
/// Name of the exchange
|
||||||
|
|||||||
@@ -208,11 +208,17 @@ namespace CryptoExchange.Net.Sockets.Default
|
|||||||
{
|
{
|
||||||
if (Parameters.RateLimiter != null)
|
if (Parameters.RateLimiter != null)
|
||||||
{
|
{
|
||||||
var rateRatio = 1.0;
|
var limitResult = await Parameters.RateLimiter.ProcessAsync(
|
||||||
if (Parameters.RateLimitAdmission != null)
|
_logger,
|
||||||
rateRatio = Parameters.RateLimitAdmission(_requestDefinition, 1).MaxUtilization;
|
Id,
|
||||||
|
RateLimitItemType.Connection,
|
||||||
var limitResult = await Parameters.RateLimiter.ProcessAsync(_logger, Id, RateLimitItemType.Connection, _requestDefinition, null, 1, Parameters.RateLimitingBehavior, null, rateRatio, _ctsSource.Token).ConfigureAwait(false);
|
_requestDefinition,
|
||||||
|
null,
|
||||||
|
1,
|
||||||
|
Parameters.RateLimitingBehavior,
|
||||||
|
null,
|
||||||
|
1.0,
|
||||||
|
_ctsSource.Token).ConfigureAwait(false);
|
||||||
if (!limitResult.Success)
|
if (!limitResult.Success)
|
||||||
return CallResult.Fail(new ClientRateLimitError("Connection limit reached"));
|
return CallResult.Fail(new ClientRateLimitError("Connection limit reached"));
|
||||||
}
|
}
|
||||||
@@ -386,7 +392,15 @@ namespace CryptoExchange.Net.Sockets.Default
|
|||||||
|
|
||||||
var bytes = Parameters.Encoding.GetBytes(data);
|
var bytes = Parameters.Encoding.GetBytes(data);
|
||||||
_logger.SocketAddingBytesToSendBuffer(Id, id, bytes);
|
_logger.SocketAddingBytesToSendBuffer(Id, id, bytes);
|
||||||
_sendBuffer.Enqueue(new SendItem { Id = id, Type = WebSocketMessageType.Text, Weight = weight, Bytes = bytes });
|
_sendBuffer.Enqueue(
|
||||||
|
new SendItem
|
||||||
|
{
|
||||||
|
Id = id,
|
||||||
|
Type = WebSocketMessageType.Text,
|
||||||
|
Weight = weight,
|
||||||
|
Bytes = bytes,
|
||||||
|
RateLimitAdmission = Parameters.RateLimitAdmissionCallbackRequest?.Invoke()
|
||||||
|
});
|
||||||
_sendEvent.Set();
|
_sendEvent.Set();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -398,7 +412,14 @@ namespace CryptoExchange.Net.Sockets.Default
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
_logger.SocketAddingBytesToSendBuffer(Id, id, data);
|
_logger.SocketAddingBytesToSendBuffer(Id, id, data);
|
||||||
_sendBuffer.Enqueue(new SendItem { Id = id, Type = WebSocketMessageType.Binary, Weight = weight, Bytes = data });
|
_sendBuffer.Enqueue(
|
||||||
|
new SendItem {
|
||||||
|
Id = id,
|
||||||
|
Type = WebSocketMessageType.Binary,
|
||||||
|
Weight = weight,
|
||||||
|
Bytes = data,
|
||||||
|
RateLimitAdmission = Parameters.RateLimitAdmissionCallbackRequest?.Invoke()
|
||||||
|
});
|
||||||
_sendEvent.Set();
|
_sendEvent.Set();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -534,9 +555,8 @@ namespace CryptoExchange.Net.Sockets.Default
|
|||||||
{
|
{
|
||||||
if (Parameters.RateLimiter != null)
|
if (Parameters.RateLimiter != null)
|
||||||
{
|
{
|
||||||
var rateRatio = 1.0;
|
var admission = data.RateLimitAdmission ?? Parameters.RateLimitAdmissionCallbackOptions?.Invoke(_requestDefinition, data.Weight);
|
||||||
if (Parameters.RateLimitAdmission != null)
|
var rateRatio = admission?.MaxUtilizationRatio ?? 1.0;
|
||||||
rateRatio = Parameters.RateLimitAdmission(_requestDefinition, data.Weight).MaxUtilization;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -1035,6 +1055,11 @@ namespace CryptoExchange.Net.Sockets.Default
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public WebSocketMessageType Type { get; set; }
|
public WebSocketMessageType Type { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Rate limit admission override
|
||||||
|
/// </summary>
|
||||||
|
public RateLimitAdmission? RateLimitAdmission { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The bytes to send
|
/// The bytes to send
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user