UNPKG

@bitrix24/b24jssdk

Version:

Bitrix24 REST API JavaScript SDK

136 lines (133 loc) 3.85 kB
/** * @package @bitrix24/b24jssdk * @version 1.1.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 */ async waitIfNeeded(requestId, method, params) { if (!this.#config.enabled) { return 0; } const delay = this.#calculateDelay(requestId, method, params); if (delay > 0) { this.incrementAdaptiveDelays(); this.#stats.totalAdaptiveDelay += delay; } return delay; } /** * Calculates adaptive delay based on previous experience */ #calculateDelay(requestId, method, params) { if (method === "batch") { return this.#calculateBatchDelay(requestId, params); } 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; } /** * For `batch`, applies adaptive delay based on previous experience from commands */ #calculateBatchDelay(requestId, params) { let maxDelay = 0; if (!params?.cmd || !Array.isArray(params.cmd)) { return maxDelay; } const batchMethods = params.cmd.map((row) => row.split("?")[0]).filter(Boolean); const batchMethodsUnique = [...new Set(batchMethods)]; for (const methodName of batchMethodsUnique) { const delay = this.#calculateDelay(requestId, `batch::${methodName}`, {}); maxDelay = Math.max(maxDelay, delay); } return maxDelay; } 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 } }); } // endregion //// } export { AdaptiveDelayer }; //# sourceMappingURL=adaptive-delayer.mjs.map