all files / src/ TokenBucket.js

100% Statements 22/22
100% Branches 16/16
100% Functions 5/5
100% Lines 22/22
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93                                            21×   21×   21× 21×   21×               20× 20×                                                                              
'use strict';
 
const DEFAULT_LIMIT              = 25;
const DEFAULT_INCREMENT_INTERVAL = 5000;
const DEFAULT_INCREMENT          = 1;
 
/**
 * TokenBucket
 *
 * Handles how many tokens are available at any given time based on
 * the configuration set and the token bucket algorithm.
 *
 * @see https://en.wikipedia.org/wiki/Token_bucket
 */
class TokenBucket {
 
  /**
   * Creates a TokenBucket object.
   *
   * @param {object} config configuration values
   * @param {integer} [config.limit=25] The max amount of tokens per incrementInterval.
   * @param {integer} [config.incrementInterval=5000] The time in ms before tokens will increment.
   * @param {integer} [config.increment=1] The amount of tokens that will increment each incrementInterval.
   */
  constructor(config) {
    config = config || {};
 
    const incrementInterval = config.incrementInterval || DEFAULT_INCREMENT_INTERVAL;
 
    this.limit = this.tokens = config.limit || DEFAULT_LIMIT;
    this.increment = config.increment || DEFAULT_INCREMENT;
 
    this._interval = setInterval(() => {
      this._incrementTokens();
    }, incrementInterval);
  }
 
  /**
   * Cleans up the interval set by the constructor.
   */
  destroy() {
    clearInterval(this._interval);
    this._interval = null;
  }
 
  /**
   * Helper to increment tokens on the interval.
   *
   * @private
   */
  _incrementTokens() {
    if (this.tokens < this.limit) {
      this.tokens += this.increment;
 
      if (this.tokens > this.limit) {
        this.tokens = this.limit;
      }
    }
  }
 
  /**
   * Decrements the amount of tokens available based on amount
   * and returns the value.
   *
   * @param {integer} [amount=1] The number to decrement by
   * @return {integer} The remaining available requests for the identifier
   */
  decrementTokens(amount) {
    amount = amount || 1;
 
    if (this.tokens >= amount) {
      this.tokens -= amount;
    }
    else {
      throw new Error('not enough tokens');
    }
 
    return this.tokens; 
  }
 
  /**
   * Returns the currently available tokens.
   *
   * @return {integer} The remaining available requests for the identifier
   */
  getTokensRemaining() {
    return this.tokens;
  }
 
};
 
module.exports = TokenBucket;