1
0
mirror of https://github.com/JKorf/CryptoExchange.Net.git synced 2026-10-19 01:20:56 +00:00
This commit is contained in:
Jkorf
2026-08-27 15:57:28 +02:00
parent d93d6b7a2e
commit 32e74e9bc4
23 changed files with 874 additions and 60 deletions
+92 -2
View File
@@ -98,6 +98,10 @@ namespace CryptoExchange.Net.Clients
/// Configured environment name
/// </summary>
public abstract string EnvironmentName { get; }
/// <summary>
/// Request coalescer
/// </summary>
protected RequestCoalescer RequestCoalescer { get; }
/// <summary>
/// ctor
@@ -123,6 +127,7 @@ namespace CryptoExchange.Net.Clients
{
TimeOffsetManager.RegisterRestApi(ClientName);
RequestCoalescer = new RequestCoalescer(_logger);
RequestFactory.Configure(options, httpClient);
}
@@ -177,8 +182,7 @@ namespace CryptoExchange.Net.Clients
/// <param name="weight">Override the request weight for this request definition, for example when the weight depends on the parameters</param>
/// <param name="weightSingleLimiter">Specify the weight to apply to the individual rate limit guard for this request</param>
/// <param name="rateLimitKeySuffix">An additional optional suffix for the key selector. Can be used to make rate limiting work based on parameters.</param>
/// <returns></returns>
protected virtual async Task<HttpResult<T>> SendAsync<T>(
protected virtual Task<HttpResult<T>> SendAsync<T>(
RequestDefinition definition,
Parameters? uriParameters,
Parameters? bodyParameters,
@@ -187,6 +191,61 @@ namespace CryptoExchange.Net.Clients
int? weight = null,
int? weightSingleLimiter = null,
string? rateLimitKeySuffix = null)
{
if (!ShouldCoalesce(definition, additionalHeaders))
{
return SendCoreAsync<T>(
definition,
uriParameters,
bodyParameters,
cancellationToken,
additionalHeaders,
weight,
weightSingleLimiter,
rateLimitKeySuffix);
}
var key = GetRequestCoalescingKey<T>(
definition,
uriParameters);
return RequestCoalescer.ExecuteAsync(
key,
requestCancellationToken => SendCoreAsync<T>(
definition,
uriParameters,
bodyParameters,
requestCancellationToken,
additionalHeaders,
weight,
weightSingleLimiter,
rateLimitKeySuffix),
() => HttpResult.Fail<T>(
Exchange,
new CancellationRequestedError()),
cancellationToken);
}
/// <summary>
/// Send a request to the base address based on the request definition
/// </summary>
/// <typeparam name="T">Response type</typeparam>
/// <param name="definition">Request definition</param>
/// <param name="uriParameters">Request query parameters</param>
/// <param name="bodyParameters">Request body parameters</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <param name="additionalHeaders">Additional headers for this request</param>
/// <param name="weight">Override the request weight for this request definition, for example when the weight depends on the parameters</param>
/// <param name="weightSingleLimiter">Specify the weight to apply to the individual rate limit guard for this request</param>
/// <param name="rateLimitKeySuffix">An additional optional suffix for the key selector. Can be used to make rate limiting work based on parameters.</param>
protected virtual async Task<HttpResult<T>> SendCoreAsync<T>(RequestDefinition definition,
Parameters? uriParameters,
Parameters? bodyParameters,
CancellationToken cancellationToken,
Dictionary<string, string>? additionalHeaders = null,
int? weight = null,
int? weightSingleLimiter = null,
string? rateLimitKeySuffix = null)
{
var requestId = ExchangeHelpers.NextId();
if (definition.Authenticated && GetAuthenticationProvider() == null)
@@ -688,7 +747,10 @@ namespace CryptoExchange.Net.Clients
stringData = stringSerializer.Serialize(parameters.BodyValue);
}
else
{
stringData = stringSerializer.Serialize(parameters);
}
request.SetContent(stringData, RequestBodyContentEncoding, contentType);
}
else if (contentType == Constants.FormContentHeader)
@@ -808,6 +870,34 @@ namespace CryptoExchange.Net.Clients
return definition.FullUrl + definition + parameters?.ToFormData();
}
/// <summary>
/// Whether a request can be coalesced or not
/// </summary>
protected virtual bool ShouldCoalesce(
RequestDefinition definition,
Dictionary<string, string>? additionalHeaders)
{
return ClientOptions.RequestCoalescingEnabled // Enabled in client options
&& !definition.PreventRequestCoalescing // Enabled in request definition
&& definition.Method == HttpMethod.Get // Is a GET request
&& !definition.Authenticated // Not an authenticated request
&& (additionalHeaders == null || additionalHeaders.Count == 0); // No additional headers that might change the response
}
/// <summary>
/// Get a unique key for coalescing requests based on the request definition, parameters, and the type of the expected response.
/// </summary>
protected virtual RequestCoalescingKey GetRequestCoalescingKey<T>(
RequestDefinition definition,
Parameters? uriParameters)
{
return new RequestCoalescingKey(
definition.Method.Method,
definition.FullUrl,
uriParameters?.ToFormData(),
typeof(T));
}
/// <inheritdoc />
public virtual void SetOptions(UpdateOptions options)
{