I have several GraphServiceClient
s and I'm using them to retrieve information from Microsoft Graph API. There's a throttle on the GraphServiceClient
calls. As far as I understood from this documentation, you can't call APIs more than 10,000 times in a 10-minute time frame and you can only use 4 concurrent requests at the same time. What's a thread-safe and efficient way to check if I have reached the maximum limit?
My implementation
I came up with this but I'm not sure if it's actually how the Microsoft Graph is checking for the limits.
public class ThrottledClient
{
private readonly TimeSpan _throttlePeriod;
private readonly int _throttleLimit;
public ThrottledClient(int throttleLimit, TimeSpan throttlePeriod)
{
_throttleLimit = throttleLimit;
_throttlePeriod = throttlePeriod;
}
private readonly ConcurrentQueue<DateTime> _requestTimes = new();
public required GraphServiceClient GraphClient { get; set; }
public async Task CheckThrottleAsync(CancellationToken cancellationToken)
{
_requestTimes.Enqueue(DateTime.UtcNow);
if(_requestTimes.Count > _throttleLimit)
{
Console.WriteLine($"Count limit, {DateTime.Now:HH:mm:ss}");
_requestTimes.TryDequeue(out var oldestRequestTime);
var timeRemaining = oldestRequestTime + _throttlePeriod - DateTime.UtcNow;
if(timeRemaining > TimeSpan.Zero)
{
Console.WriteLine($"Sleeping for {timeRemaining}");
await Task.Delay(timeRemaining, cancellationToken).ConfigureAwait(false);
Console.WriteLine($"Woke up, {DateTime.Now:HH:mm:ss}");
}
}
}
}
public class Engine
{
public async Task RunAsync()
{
var client = GetClient();
await client.CheckThrottleAsync(_cts.Token).ConfigureAwait(false);
await DoSomethingAsync(client.GraphClient).ConfigureAwait(false);
}
}
I can think of other ways to use like lock
or Semaphore
but again, I'm not sure if I'm thinking about this correctly.