Skip to content

Rate Limit is violated in a sense if I remove 1 token every second when I define bucket interval as 1 minute #25

@amlandas

Description

@amlandas

I implement a queue to hold requests until the condition t remove a token holds true, and if it does I remove a token and proceed with my task. I define my bucket size to be 3, and the rate limit interval as 1 minute. Given below is the code I used initially to implement rate limiter.

Throttler.prototype.checkAndExecute = function ()
  if (this.queue.length > 0) 
    if (this.limiter.getTokensRemaining() > 0)
      if (this.limiter.tryRemoveTokens(1)) {
        var job = that.queue.shift();
        if (job) {
          // do my job....
        }
      }
    }
  }
};

I wrap the above function inside an interval to check the queue contents and trigger the job if a token is available. Code given below -

this.peekInterval = setInterval( function() {
    that.checkAndExecute();
  }, 1000 );

The issue is that when I send 10 jobs to the queue, the first 3 are picked immediately by removing tokens from the bucket and executed. So, ideally, my request to remove 1 more token should not be allowed until at least 60 seconds have passed since I removed the first token. But, the bcuket gets filled up with another token in 20 seconds (60 seconds / 3), and the 4th job gets to execute in the 21st second. Thus, in the 1 minute interval since the first token was removed, more than 3 jobs got executed (in fact 5 jobs execute in the first minute itself), which violates the rate limit I set - 3 jobs per minute.

I am able to work around with this by modifying the checkAndExecute function in the way below -

Throttler.prototype.checkAndExecute = function () {
  if (that.queue.length > 0) {
    if (this.limiter.getTokensRemaining() >= this.bucketSize) {
      if (this.limiter.tryRemoveTokens(1)) {
        var job = that.queue.shift();
        if (job) {
          // do my job....
        }
      }
    }
  }
};

I'm not sure if anyone else has faced this scenario like I did, but just wanted to flag this out.

I understand that how the node rate-limiter and token-bucket functions holds good when a user wants to implement the token bucket algorithm, but in true definition of a rate limiter, the bucket should not be filled with additional tokens until the time interval since the removal of the 1st token has expired.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions