JM Tech Power

jm-tech-power-official/Flash Download

A desktop download manager that opens up to 32 connections against one file and can send each of them out a different proxy route.

Public Uncategorized
Clone jm-tech-power-official/flash-download.jmproj
src/main/engine/limiter.js
'use strict';

/**
 * Token bucket shared by every lane in the app, so a speed limit applies to the
 * download as a whole rather than per connection (16 lanes x 1 MB/s is not a
 * 1 MB/s limit, and users mean the former).
 */
class Limiter {
  constructor() {
    this.bps = 0;           // 0 === unlimited
    this.tokens = 0;
    this.waiters = [];
    this.timer = null;
  }

  setLimit(bytesPerSecond) {
    this.bps = Math.max(0, Number(bytesPerSecond) || 0);
    this.tokens = this.bps;
    if (this.bps && !this.timer) {
      this.timer = setInterval(() => this.refill(), 100);
      if (this.timer.unref) this.timer.unref();
    } else if (!this.bps && this.timer) {
      clearInterval(this.timer);
      this.timer = null;
      this.release();
    }
  }

  /** @returns {Promise<void>|null} null means "proceed immediately" */
  take(bytes) {
    if (!this.bps) return null;
    this.tokens -= bytes;
    if (this.tokens >= 0) return null;
    return new Promise((resolve) => this.waiters.push(resolve));
  }

  refill() {
    this.tokens = Math.min(this.bps, this.tokens + this.bps / 10);
    if (this.tokens >= 0) this.release();
  }

  release() {
    const waiting = this.waiters;
    this.waiters = [];
    for (const resolve of waiting) resolve();
  }

  stop() {
    if (this.timer) clearInterval(this.timer);
    this.timer = null;
    this.release();
  }
}

module.exports = { Limiter };