tencentcloud-edgeone-migration-nodejs-v2
Version:
tencentcloud cdn config copy to edgeone
152 lines • 4.56 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExternalBucket = exports.InternalBucket = exports.BasicBucket = void 0;
const process_1 = require("process");
const utils_1 = require("../utils");
/**
* 基础令牌桶
* 桶内剩余可用令牌,不会增加
*/
class BasicBucket {
constructor(total, partition, overflow = false) {
this.total = total;
this.partition = partition;
this.overflow = overflow;
this.capacity = ~~(this.total / this.partition);
this.remains = this.capacity;
}
get partitionTokens() {
return this.capacity;
}
get remainingTokens() {
return this.remains;
}
setPartition(partition) {
this.recalculate(partition);
this.partition = partition;
this.capacity = ~~(this.total / this.partition);
}
consume(tokens, preroll) {
if (!(this.remains >= tokens)) {
return false;
}
if (!preroll) {
this.remains -= tokens;
/*
* note:
* 由于 `tokens` 可能为负值,
* 导致计算出的 `remains` 超过总值 `capacity`
*/
if (!this.overflow && this.remains > this.capacity) {
this.remains = this.capacity;
}
}
return true;
}
drain() {
const { remains } = this;
this.remains = 0;
return remains;
}
recalculate(partition) {
let remains = ~~(this.total / partition) - (this.capacity - this.remains);
if (remains < 0) {
remains = 0;
}
this.remains = remains;
}
}
exports.BasicBucket = BasicBucket;
/**
* 内部令牌桶
* 桶内剩余可用令牌,由内部新增
*/
class InternalBucket extends BasicBucket {
constructor(total, partition, overflow = false, duration, options) {
super(total, partition, overflow);
this.duration = duration;
this.options = options;
this.isAccessed = false;
this.idlePeriods = 0;
this.period = 0;
this.onWakUp(false);
}
get currentPeriod() {
return this.period;
}
consume(tokens, preroll) {
this.isAccessed = true;
this.wake();
return super.consume(tokens, preroll);
}
// #region Wake-sleep
onWakUp(immediate) {
if (immediate) {
this.onTimeout();
}
this.timer = setInterval(() => this.onTimeout.bind(this), this.duration).unref();
}
wake() {
if (this.timer === undefined) {
if (this.sleepTime === undefined) {
(0, utils_1.UNREACHABLE)();
}
const elapsedTime = Math.floor(((0, process_1.uptime)() - this.sleepTime) * utils_1.kSeconds);
this.period += Math.floor(elapsedTime / this.duration);
const interval = elapsedTime % this.duration;
if (interval === 0) {
this.onWakUp(false);
}
else {
this.timer = setTimeout(this.onWakUp.bind(this, true), interval).unref();
}
}
}
sleep() {
if (this.timer !== undefined) {
clearInterval(this.timer);
this.timer = undefined;
}
this.sleepTime = (0, process_1.uptime)();
this.idlePeriods = 0;
this.isAccessed = false;
}
// #endregion
onTimeout() {
this.period += 1;
this.remains = this.capacity;
if (this.isAccessed) {
this.idlePeriods = 0;
}
else {
this.idlePeriods += 1;
}
this.isAccessed = false;
/*
* 为了降低消耗,当超过 `this.options.idlePeriod` 周期没有访问时,
* 自动进入休眠状态(停止一切定时器)
*
* note:
* 如外部不再强引用(WeakMap 为弱引用)当前对象,当进入休眠状态后,当前对象会被自动回收
*/
if (this.idlePeriods > this.options.idlePeriod) {
this.sleep();
}
}
}
exports.InternalBucket = InternalBucket;
/**
* 外部令牌桶
* 桶内剩余可用令牌,由外部调整
*/
class ExternalBucket extends BasicBucket {
update(value) {
let remains = ~~((this.total - value) / this.partition);
if (remains < 0) {
remains = 0;
}
this.remains = remains;
}
}
exports.ExternalBucket = ExternalBucket;
//# sourceMappingURL=bucket.js.map