feat(web): implement KisApiClient request throttling to prevent KIS OpenAPI rate limits
This commit is contained in:
@@ -32,6 +32,8 @@ public class KisApiClient : IKisApiClient
|
||||
private readonly ITokenCache _tokenCache;
|
||||
private readonly ILogger<KisApiClient> _logger;
|
||||
private static readonly ConcurrentDictionary<string, SemaphoreSlim> TokenLocks = new();
|
||||
private readonly SemaphoreSlim _rateLimitSemaphore = new(1, 1);
|
||||
private DateTime _lastRequestTime = DateTime.MinValue;
|
||||
|
||||
public KisApiClient(HttpClient httpClient, ITokenCache tokenCache, ILogger<KisApiClient> logger)
|
||||
{
|
||||
@@ -152,6 +154,7 @@ public class KisApiClient : IKisApiClient
|
||||
foreach (var header in headers)
|
||||
request.Headers.Add(header.Key, header.Value);
|
||||
|
||||
await ApplyRateLimitDelayAsync(account);
|
||||
var response = await _httpClient.SendAsync(request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
@@ -195,6 +198,7 @@ public class KisApiClient : IKisApiClient
|
||||
{
|
||||
try
|
||||
{
|
||||
await ApplyRateLimitDelayAsync(creds.Account);
|
||||
var response = await _httpClient.PostAsJsonAsync(
|
||||
$"{creds.Domain}/oauth2/tokenP",
|
||||
tokenRequest
|
||||
@@ -318,4 +322,29 @@ public class KisApiClient : IKisApiClient
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ApplyRateLimitDelayAsync(string account)
|
||||
{
|
||||
await _rateLimitSemaphore.WaitAsync();
|
||||
try
|
||||
{
|
||||
var mode = account.Contains("real", StringComparison.OrdinalIgnoreCase) ? "real" : "mock";
|
||||
int minIntervalMs = mode == "real" ? 150 : 400;
|
||||
|
||||
var now = DateTime.UtcNow;
|
||||
var elapsed = (now - _lastRequestTime).TotalMilliseconds;
|
||||
if (elapsed < minIntervalMs)
|
||||
{
|
||||
var delay = minIntervalMs - (int)elapsed;
|
||||
_logger.LogDebug("Rate limit throttling: delaying for {Delay}ms (Mode: {Mode})", delay, mode);
|
||||
await Task.Delay(delay);
|
||||
}
|
||||
|
||||
_lastRequestTime = DateTime.UtcNow;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_rateLimitSemaphore.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user