@freemework/common
Version:
Common library of the Freemework Project.
102 lines • 3.94 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.FLimitInternalTimeSpanLimit = void 0;
const f_limit_exception_js_1 = require("../f_limit_exception.js");
const f_internal_limit_sync_base_js_1 = require("./f_internal_limit_sync_base.js");
const f_internal_limit_token_deferred_js_1 = require("./f_internal_limit_token_deferred.js");
class FLimitInternalTimeSpanLimit extends f_internal_limit_sync_base_js_1.FInternalLimitSyncBase {
_maxTokens;
_activeTokenDefers;
_delay;
_clearTimeoutFunc;
_setTimeoutFunc;
_timers = [];
constructor(delay, hitCount, stubs = {
clearTimeoutFunc: (...args) => clearTimeout(...args),
setTimeoutFunc: (...args) => setTimeout(...args)
}) {
super();
this._maxTokens = hitCount;
this._delay = delay;
this._clearTimeoutFunc = stubs.clearTimeoutFunc;
this._setTimeoutFunc = stubs.setTimeoutFunc;
this._activeTokenDefers = [];
}
get availableWeight() {
if (super.disposed) {
throw new Error("Wrong operation on disposed object");
}
return this._maxTokens - this._activeTokenDefers.reduce((p, c) => p + c.weight, 0);
}
get maxWeight() {
if (super.disposed) {
throw new Error("Wrong operation on disposed object");
}
return this._maxTokens;
}
accrueToken(weight) {
super.verifyNotDisposed();
if (this.availableWeight < weight) {
throw new f_limit_exception_js_1.FLimitException("No any available tokens");
}
let defer = null;
{ // local scope
const realDefer = {
...f_internal_limit_token_deferred_js_1.FInternalLimitTokenDeferred.create(weight),
finalize: () => {
realDefer.resolve();
const index = this._activeTokenDefers.indexOf(realDefer);
this._activeTokenDefers.splice(index, 1);
this.raiseReleaseToken();
},
finalizing: false
};
this._activeTokenDefers.push(realDefer);
defer = realDefer;
}
const token = {
commit: () => {
if (defer !== null) {
const selfDefer = defer;
defer = null;
selfDefer.finalizing = true;
if (!super.disposing) {
const timer = this._setTimeoutFunc(() => {
const timerIndex = this._timers.indexOf(timer);
if (timerIndex !== -1) {
this._timers.splice(timerIndex, 1);
}
selfDefer.finalize();
}, this._delay);
this._timers.push(timer);
}
else {
selfDefer.finalize();
}
}
},
rollback: () => {
if (defer !== null) {
const selfDefer = defer;
defer = null;
selfDefer.finalizing = true;
selfDefer.finalize();
}
}
};
return token;
}
async onDispose() {
this._timers.slice().forEach(timer => {
this._clearTimeoutFunc(timer);
const timerIndex = this._timers.indexOf(timer);
if (timerIndex !== -1) {
this._timers.splice(timerIndex, 1);
}
});
this._activeTokenDefers.filter(w => w.finalizing).forEach(d => d.finalize());
await Promise.all(this._activeTokenDefers.map(d => d.promise));
}
}
exports.FLimitInternalTimeSpanLimit = FLimitInternalTimeSpanLimit;
//# sourceMappingURL=f_limit_internal_time_span_limit.js.map