using System; using System.Threading.Tasks; namespace Amazon.SellingPartnerApiSDK.Misc { internal class RateLimits { internal RateLimits(decimal rate, int burst) { Rate = rate; Burst = burst; LastRequest = DateTime.UtcNow; RequestsSent = 0; } internal decimal Rate { get; set; } internal int Burst { get; set; } internal DateTime LastRequest { get; set; } internal int RequestsSent { get; set; } private int GetRatePeriodMs() { return (int)(1 / Rate * 1000 / 1); } public RateLimits NextRate(RateLimitType rateLimitType) { if (RequestsSent < 0) RequestsSent = 0; var ratePeriodMs = GetRatePeriodMs(); var nextRequestsSent = RequestsSent + 1; var nextRequestsSentTxt = nextRequestsSent > Burst ? "FULL" : nextRequestsSent.ToString(); if (AmazonCredential.DebugMode) { string output = $"[RateLimits ,{rateLimitType,15}]: {DateTime.UtcNow.ToString(),10}\t Request/Burst: {nextRequestsSentTxt}/{Burst}\t Rate: {Rate}/{ratePeriodMs}ms"; Console.WriteLine(output); } if (RequestsSent >= Burst) { var lastRequestTime = LastRequest; while (true) { lastRequestTime = lastRequestTime.AddMilliseconds(ratePeriodMs); if (lastRequestTime > DateTime.UtcNow) break; else RequestsSent -= 1; if (RequestsSent <= 0) { RequestsSent = 0; break; } } } if (RequestsSent >= Burst) { LastRequest = LastRequest.AddMilliseconds(ratePeriodMs); var tempLastRequest = LastRequest; while (tempLastRequest >= DateTime.UtcNow) Task.Delay(100).Wait(); } if (RequestsSent + 1 <= Burst) RequestsSent += 1; LastRequest = DateTime.UtcNow; return this; } internal void SetRateLimit(decimal rate) { Rate = rate; } internal void Delay() { Task.Delay(GetRatePeriodMs()).Wait(); } } }