UNPKG

@bitrix24/b24jssdk

Version:

Bitrix24 REST API JavaScript SDK

123 lines (120 loc) • 3.45 kB
/** * @package @bitrix24/b24jssdk * @version 3.0.0 * @copyright (c) 2026 Bitrix24 * @license MIT * @see https://github.com/bitrix24/b24jssdk * @see https://bitrix24.github.io/b24jssdk/ */ import { LoggerFactory } from '../../../logger/logger-factory.mjs'; var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); class AdaptiveDelayer { static { __name(this, "AdaptiveDelayer"); } #config; #operatingLimiter; #stats = { adaptiveDelays: 0, totalAdaptiveDelay: 0 }; _logger; getTitle() { return "adaptiveDelayer"; } constructor(config, operatingLimiter) { this._logger = LoggerFactory.createNullLogger(); this.#config = config; this.#operatingLimiter = operatingLimiter; } // region Logger //// setLogger(logger) { this._logger = logger; } getLogger() { return this._logger; } // endregion //// async canProceed(_requestId, _method, _params) { return true; } /** * Returns an adaptive delay based on previous experience. * * `_params` is unused: it carried the batch command list, which mattered only * while a batch was delayed on the busiest method inside it. A batch is now * delayed on the `batch` budget the portal bills it against. The parameter * stays because {@link ILimiter} declares it. */ async waitIfNeeded(requestId, method, _params) { if (!this.#config.enabled) { return 0; } const delay = this.#calculateDelay(requestId, method); if (delay > 0) { this.incrementAdaptiveDelays(); this.#stats.totalAdaptiveDelay += delay; } return delay; } /** * Calculates adaptive delay based on previous experience */ #calculateDelay(requestId, method) { const stats = this.#operatingLimiter.getMethodStat(method); if (typeof stats === "undefined") { return 0; } const usagePercent = stats.operating / this.#operatingLimiter.limitMs * 100; if (usagePercent > this.#config.thresholdPercent) { let adaptiveDelay = 0; const now = Date.now(); if (stats.operating_reset_at > now) { adaptiveDelay += (stats.operating_reset_at - now) * this.#config.coefficient; } else { adaptiveDelay += 7e3; } const waitDelay = Number.parseInt(Math.min(adaptiveDelay, this.#config.maxDelay).toFixed(0)); this.#logStat(requestId, method, usagePercent, adaptiveDelay, waitDelay); return waitDelay; } return 0; } async updateStats(_requestId, _method, _data) { } async reset() { this.#stats = { adaptiveDelays: 0, totalAdaptiveDelay: 0 }; } getStats() { return { ...this.#stats, adaptiveDelayAvg: this.#stats.adaptiveDelays > 0 ? this.#stats.totalAdaptiveDelay / this.#stats.adaptiveDelays : 0 }; } async setConfig(config) { this.#config = config; } incrementAdaptiveDelays() { this.#stats.adaptiveDelays++; } // region Log //// #logStat(requestId, method, percent, adaptiveDelay, waitDelay) { this.getLogger().debug(`${this.getTitle()} state for method ${method}`, { requestId, method, percent: Number.parseFloat(percent.toFixed(2)), delays: { calculated: adaptiveDelay, actual: waitDelay } }).catch(() => { }); } // endregion //// } export { AdaptiveDelayer }; //# sourceMappingURL=adaptive-delayer.mjs.map