Question

I'm wondering how to implement a wrapper for a REST service that needs throttling. The service is rate limited to e.g. "Max 60 calls per minute" or similar. Overusing the resource means my client is blocked for an extended time so I must take care to not let that happen, thus I'd like the wrapper itself to be rate limited.

Edit: removed final idea and posted it as the answer

Was it helpful?

Solution

Answering my own question, inspired by the comment by @Alex, this one solves the problem of max N requests in time span T. It holds the times of the last N requests in a list (cyclic buffer) and allows the request if the oldest call was older than T.

public class Throttler<T>
{
   private readonly long[] callTimes;
   private int cur;      
   private readonly Func<T> func;
   private readonly TimeSpan interval;
   private readonly object padlock = new object();    

   public Throttler(Func<T> func, int maxCalls, TimeSpan interval)
   {
      this.func = func;
      callTimes = new long[maxCalls];
      this.interval = interval;
      cur = 0;
   }

   public T Call()
   {
      lock (padlock)
      {
         do
         {
            long oldestCall = callTimes[(cur + 1)%callTimes.Length];
            long now = DateTime.UtcNow.Ticks;               
            if (now - oldestCall > interval.Ticks)
            {                 
               cur = (cur + 1) % callTimes.Length;                  
               callTimes[cur] = now;
               return func();
            }
            int sleepTime = (int)((interval.Ticks - (now - oldestCall))/TimeSpan.TicksPerMillisecond) + 1;               
            Thread.Sleep(sleepTime);               
         } while (true);
      }
   }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top