@bitrix24/b24jssdk
Version:
Bitrix24 REST API JavaScript SDK
1 lines • 8.27 kB
Source Map (JSON)
{"version":3,"file":"adaptive-delayer.mjs","sources":["../../../../../src/core/http/limiters/adaptive-delayer.ts"],"sourcesContent":["import type { AdaptiveConfig, ILimiter } from '../../../types/limiters'\nimport type { OperatingLimiter } from './operating-limiter'\nimport type { LoggerInterface } from '../../../types/logger'\nimport { LoggerFactory } from '../../../logger'\n\n/**\n * Adaptive delayer\n *\n * @todo docs\n */\nexport class AdaptiveDelayer implements ILimiter {\n #config: AdaptiveConfig\n #operatingLimiter: OperatingLimiter\n #stats = {\n adaptiveDelays: 0,\n totalAdaptiveDelay: 0\n }\n\n private _logger: LoggerInterface\n\n getTitle(): string {\n return 'adaptiveDelayer'\n }\n\n constructor(config: AdaptiveConfig, operatingLimiter: OperatingLimiter) {\n this._logger = LoggerFactory.createNullLogger()\n this.#config = config\n this.#operatingLimiter = operatingLimiter\n }\n\n // region Logger ////\n setLogger(logger: LoggerInterface): void {\n this._logger = logger\n }\n\n getLogger(): LoggerInterface {\n return this._logger\n }\n // endregion ////\n\n async canProceed(_requestId: string, _method: string, _params?: any): Promise<boolean> {\n return true // Adaptive delay doesn't block, only delays\n }\n\n /**\n * Returns an adaptive delay based on previous experience\n */\n async waitIfNeeded(requestId: string, method: string, params?: any): Promise<number> {\n if (!this.#config.enabled) {\n return 0\n }\n\n const delay = this.#calculateDelay(requestId, method, params)\n if (delay > 0) {\n this.incrementAdaptiveDelays()\n this.#stats.totalAdaptiveDelay += delay\n }\n\n return delay\n }\n\n /**\n * Calculates adaptive delay based on previous experience\n */\n #calculateDelay(requestId: string, method: string, params?: any): number {\n if (method === 'batch') {\n return this.#calculateBatchDelay(requestId, params)\n }\n\n const stats = this.#operatingLimiter.getMethodStat(method)\n\n if (typeof stats === 'undefined') {\n return 0\n }\n\n const usagePercent = (stats.operating / this.#operatingLimiter.limitMs) * 100\n\n if (usagePercent > this.#config.thresholdPercent) {\n let adaptiveDelay = 0\n\n // Calculate based on previous delay or default\n const now = Date.now()\n if (stats.operating_reset_at > now) {\n adaptiveDelay += (stats.operating_reset_at - now) * this.#config.coefficient\n } else {\n adaptiveDelay += 7_000 // 7 seconds by default\n }\n\n const waitDelay = Number.parseInt(Math.min(adaptiveDelay, this.#config.maxDelay).toFixed(0))\n\n this.#logStat(requestId, method, usagePercent, adaptiveDelay, waitDelay)\n return waitDelay\n }\n\n return 0\n }\n\n /**\n * For `batch`, applies adaptive delay based on previous experience from commands\n */\n #calculateBatchDelay(requestId: string, params: any): number {\n let maxDelay = 0\n\n if (!params?.cmd || !Array.isArray(params.cmd)) {\n return maxDelay\n }\n\n const batchMethods = params.cmd\n .map((row: string) => row.split('?')[0])\n .filter(Boolean)\n\n const batchMethodsUnique = [...new Set(batchMethods)]\n\n for (const methodName of batchMethodsUnique) {\n const delay = this.#calculateDelay(requestId, `batch::${methodName}`, {})\n maxDelay = Math.max(maxDelay, delay)\n }\n\n return maxDelay\n }\n\n async updateStats(_requestId: string, _method: string, _data: any): Promise<void> {\n // Adaptive delayer updates based on operating limiter\n }\n\n async reset(): Promise<void> {\n this.#stats = {\n adaptiveDelays: 0,\n totalAdaptiveDelay: 0\n }\n }\n\n getStats(): {\n adaptiveDelays: number\n totalAdaptiveDelay: number\n adaptiveDelayAvg: number\n } {\n return {\n ...this.#stats,\n adaptiveDelayAvg: this.#stats.adaptiveDelays > 0\n ? this.#stats.totalAdaptiveDelay / this.#stats.adaptiveDelays\n : 0\n }\n }\n\n async setConfig(config: AdaptiveConfig): Promise<void> {\n this.#config = config\n }\n\n incrementAdaptiveDelays(): void {\n this.#stats.adaptiveDelays++\n }\n\n // region Log ////\n #logStat(requestId: string, method: string, percent: number, adaptiveDelay: number, waitDelay: number) {\n this.getLogger().debug(`${this.getTitle()} state for method ${method}`, {\n requestId,\n method,\n percent: Number.parseFloat(percent.toFixed(2)),\n delays: {\n calculated: adaptiveDelay,\n actual: waitDelay\n }\n })\n }\n // endregion ////\n}\n"],"names":[],"mappings":"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"}