1
0
mirror of https://github.com/JKorf/CryptoExchange.Net synced 2025-06-07 16:06:15 +00:00

Added rate limit update event

This commit is contained in:
Jkorf 2024-11-13 14:29:43 +01:00
parent d21792d04c
commit 48797038be
7 changed files with 71 additions and 17 deletions

View File

@ -110,7 +110,7 @@ namespace CryptoExchange.Net.RateLimiting.Guards
var delay = tracker.GetWaitTime(requestWeight); var delay = tracker.GetWaitTime(requestWeight);
if (delay == default) if (delay == default)
return LimitCheck.NotNeeded; return LimitCheck.NotNeeded(Limit, TimeSpan, tracker.Current);
return LimitCheck.Needed(delay, Limit, TimeSpan, tracker.Current); return LimitCheck.Needed(delay, Limit, TimeSpan, tracker.Current);
} }

View File

@ -64,7 +64,7 @@ namespace CryptoExchange.Net.RateLimiting.Guards
var delay = tracker.GetWaitTime(requestWeight); var delay = tracker.GetWaitTime(requestWeight);
if (delay == default) if (delay == default)
return LimitCheck.NotNeeded; return LimitCheck.NotNeeded(_limit, _period, tracker.Current);
return LimitCheck.Needed(delay, _limit, _period, tracker.Current); return LimitCheck.Needed(delay, _limit, _period, tracker.Current);
} }

View File

@ -16,6 +16,11 @@ namespace CryptoExchange.Net.RateLimiting.Interfaces
/// </summary> /// </summary>
event Action<RateLimitEvent> RateLimitTriggered; event Action<RateLimitEvent> RateLimitTriggered;
/// <summary>
/// Event when the rate limit is updated. Note that it's only updated when a request is send, so there are no specific updates when the current usage is decaying.
/// </summary>
event Action<RateLimitUpdateEvent>? RateLimitUpdated;
/// <summary> /// <summary>
/// Add a rate limit guard /// Add a rate limit guard
/// </summary> /// </summary>

View File

@ -45,7 +45,7 @@ namespace CryptoExchange.Net.RateLimiting
/// <summary> /// <summary>
/// No wait needed /// No wait needed
/// </summary> /// </summary>
public static LimitCheck NotNeeded { get; } = new LimitCheck(true, default, default, default, default); public static LimitCheck NotNeeded(int limit, TimeSpan period, int current) => new(true, default, limit, period, current);
/// <summary> /// <summary>
/// Wait needed /// Wait needed

View File

@ -4,10 +4,14 @@ using System;
namespace CryptoExchange.Net.RateLimiting namespace CryptoExchange.Net.RateLimiting
{ {
/// <summary> /// <summary>
/// Rate limit event /// Rate limit triggered event
/// </summary> /// </summary>
public record RateLimitEvent public record RateLimitEvent
{ {
/// <summary>
/// Id of the item the limit was checked for
/// </summary>
public int ItemId { get; set; }
/// <summary> /// <summary>
/// Name of the API limit that is reached /// Name of the API limit that is reached
/// </summary> /// </summary>
@ -52,18 +56,9 @@ namespace CryptoExchange.Net.RateLimiting
/// <summary> /// <summary>
/// ctor /// ctor
/// </summary> /// </summary>
/// <param name="apiLimit"></param> public RateLimitEvent(int itemId, string apiLimit, string limitDescription, RequestDefinition definition, string host, int current, int requestWeight, int? limit, TimeSpan? timePeriod, TimeSpan? delayTime, RateLimitingBehaviour behaviour)
/// <param name="limitDescription"></param>
/// <param name="definition"></param>
/// <param name="host"></param>
/// <param name="current"></param>
/// <param name="requestWeight"></param>
/// <param name="limit"></param>
/// <param name="timePeriod"></param>
/// <param name="delayTime"></param>
/// <param name="behaviour"></param>
public RateLimitEvent(string apiLimit, string limitDescription, RequestDefinition definition, string host, int current, int requestWeight, int? limit, TimeSpan? timePeriod, TimeSpan? delayTime, RateLimitingBehaviour behaviour)
{ {
ItemId = itemId;
ApiLimit = apiLimit; ApiLimit = apiLimit;
LimitDescription = limitDescription; LimitDescription = limitDescription;
RequestDefinition = definition; RequestDefinition = definition;

View File

@ -23,6 +23,8 @@ namespace CryptoExchange.Net.RateLimiting
/// <inheritdoc /> /// <inheritdoc />
public event Action<RateLimitEvent>? RateLimitTriggered; public event Action<RateLimitEvent>? RateLimitTriggered;
/// <inheritdoc />
public event Action<RateLimitUpdateEvent>? RateLimitUpdated;
/// <summary> /// <summary>
/// ctor /// ctor
@ -105,7 +107,7 @@ namespace CryptoExchange.Net.RateLimiting
else else
logger.RateLimitRequestFailed(itemId, definition.Path, guard.Name, guard.Description); logger.RateLimitRequestFailed(itemId, definition.Path, guard.Name, guard.Description);
RateLimitTriggered?.Invoke(new RateLimitEvent(_name, guard.Description, definition, host, result.Current, requestWeight, result.Limit, result.Period, result.Delay, rateLimitingBehaviour)); RateLimitTriggered?.Invoke(new RateLimitEvent(itemId, _name, guard.Description, definition, host, result.Current, requestWeight, result.Limit, result.Period, result.Delay, rateLimitingBehaviour));
return new CallResult(new ClientRateLimitError($"Rate limit check failed on guard {guard.Name}; {guard.Description}")); return new CallResult(new ClientRateLimitError($"Rate limit check failed on guard {guard.Name}; {guard.Description}"));
} }
@ -120,7 +122,7 @@ namespace CryptoExchange.Net.RateLimiting
else else
logger.RateLimitDelayingRequest(itemId, definition.Path, result.Delay, guard.Name, description); logger.RateLimitDelayingRequest(itemId, definition.Path, result.Delay, guard.Name, description);
RateLimitTriggered?.Invoke(new RateLimitEvent(_name, guard.Description, definition, host, result.Current, requestWeight, result.Limit, result.Period, result.Delay, rateLimitingBehaviour)); RateLimitTriggered?.Invoke(new RateLimitEvent(itemId, _name, guard.Description, definition, host, result.Current, requestWeight, result.Limit, result.Period, result.Delay, rateLimitingBehaviour));
await Task.Delay((int)result.Delay.TotalMilliseconds + 1, ct).ConfigureAwait(false); await Task.Delay((int)result.Delay.TotalMilliseconds + 1, ct).ConfigureAwait(false);
await _semaphore.WaitAsync(ct).ConfigureAwait(false); await _semaphore.WaitAsync(ct).ConfigureAwait(false);
return await CheckGuardsAsync(guards, logger, itemId, type, definition, host, apiKey, requestWeight, rateLimitingBehaviour, ct).ConfigureAwait(false); return await CheckGuardsAsync(guards, logger, itemId, type, definition, host, apiKey, requestWeight, rateLimitingBehaviour, ct).ConfigureAwait(false);
@ -133,6 +135,8 @@ namespace CryptoExchange.Net.RateLimiting
var result = guard.ApplyWeight(type, definition, host, apiKey, requestWeight); var result = guard.ApplyWeight(type, definition, host, apiKey, requestWeight);
if (result.IsApplied) if (result.IsApplied)
{ {
RateLimitUpdated?.Invoke(new RateLimitUpdateEvent(itemId, _name, guard.Description, result.Current, result.Limit, result.Period));
if (type == RateLimitItemType.Connection) if (type == RateLimitItemType.Connection)
logger.RateLimitAppliedConnection(itemId, guard.Name, guard.Description, result.Current); logger.RateLimitAppliedConnection(itemId, guard.Name, guard.Description, result.Current);
else else

View File

@ -0,0 +1,50 @@
using CryptoExchange.Net.Objects;
using System;
namespace CryptoExchange.Net.RateLimiting
{
/// <summary>
/// Rate limit update event
/// </summary>
public record RateLimitUpdateEvent
{
/// <summary>
/// Id of the item the limit was checked for
/// </summary>
public int ItemId { get; set; }
/// <summary>
/// Name of the API limit that is reached
/// </summary>
public string ApiLimit { get; set; } = string.Empty;
/// <summary>
/// Description of the limit that is reached
/// </summary>
public string LimitDescription { get; set; } = string.Empty;
/// <summary>
/// The current counter value
/// </summary>
public int Current { get; set; }
/// <summary>
/// The limit per time period
/// </summary>
public int? Limit { get; set; }
/// <summary>
/// The time period the limit is for
/// </summary>
public TimeSpan? TimePeriod { get; set; }
/// <summary>
/// ctor
/// </summary>
public RateLimitUpdateEvent(int itemId, string apiLimit, string limitDescription, int current, int? limit, TimeSpan? timePeriod)
{
ItemId = itemId;
ApiLimit = apiLimit;
LimitDescription = limitDescription;
Current = current;
Limit = limit;
TimePeriod = timePeriod;
}
}
}