all files / src/ rate_limiter.js

100% Statements 22/22
100% Branches 6/6
100% Functions 4/4
100% Lines 21/21
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                                    38× 38× 38× 38×               560× 560× 129× 129×   431×       567× 567× 567×   567× 567×        
// @flow
// Copyright (c) 2016 Uber Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the License
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions and limitations under
// the License.
 
export default class RateLimiter {
  _creditsPerSecond: number;
  _balance: number;
  _maxBalance: number;
  _lastTick: number;
 
  constructor(creditsPerSecond: number, maxBalance: number, initBalance: ?number) {
    this._creditsPerSecond = creditsPerSecond;
    this._balance = initBalance || Math.random() * maxBalance;
    this._maxBalance = maxBalance;
    this._lastTick = new Date().getTime();
  }
 
  update(creditsPerSecond: number, maxBalance: number) {
    this._updateBalance();
    this._creditsPerSecond = creditsPerSecond;
    // The new balance should be proportional to the old balance.
    this._balance = maxBalance * this._balance / this._maxBalance;
    this._maxBalance = maxBalance;
  }
 
  checkCredit(itemCost: number): boolean {
    this._updateBalance();
    if (this._balance >= itemCost) {
      this._balance -= itemCost;
      return true;
    }
    return false;
  }
 
  _updateBalance() {
    let currentTime: number = new Date().getTime();
    let elapsedTime: number = (currentTime - this._lastTick) / 1000;
    this._lastTick = currentTime;
 
    this._balance += elapsedTime * this._creditsPerSecond;
    if (this._balance > this._maxBalance) {
      this._balance = this._maxBalance;
    }
  }
}