{"version":3,"file":"manager.mjs","sources":["../../../../../src/core/http/limiters/manager.ts"],"sourcesContent":["import type { RestrictionParams, RestrictionManagerStats } from '../../../types/limiters'\nimport type { LoggerInterface } from '../../../types/logger'\nimport { LoggerFactory } from '../../../logger'\nimport { RateLimiter } from './rate-limiter'\nimport { OperatingLimiter } from './operating-limiter'\nimport { AdaptiveDelayer } from './adaptive-delayer'\n\n/**\n * Delay Management Manager\n *\n * @todo docs\n */\nexport class RestrictionManager {\n  #rateLimiter: RateLimiter\n  #operatingLimiter: OperatingLimiter\n  #adaptiveDelayer: AdaptiveDelayer\n  #config: RestrictionParams\n  #stats: Pick<RestrictionManagerStats, 'retries' | 'consecutiveErrors' | 'limitHits'> = {\n    /** Retry attempts */\n    retries: 0,\n    /** Consecutive errors */\n    consecutiveErrors: 0,\n    /** Limit triggers */\n    limitHits: 0\n  }\n\n  #errorCounts = new Map<string, number>()\n\n  private _logger: LoggerInterface\n\n  constructor(params: RestrictionParams) {\n    this._logger = LoggerFactory.createNullLogger()\n    this.#config = params\n    this.#rateLimiter = new RateLimiter(params.rateLimit!)\n    this.#operatingLimiter = new OperatingLimiter(params.operatingLimit!)\n    this.#adaptiveDelayer = new AdaptiveDelayer(params.adaptiveConfig!, this.#operatingLimiter)\n  }\n\n  // region Logger ////\n  setLogger(logger: LoggerInterface): void {\n    this._logger = logger\n    this.#rateLimiter.setLogger(this._logger)\n    this.#operatingLimiter.setLogger(this._logger)\n    this.#adaptiveDelayer.setLogger(this._logger)\n  }\n\n  getLogger(): LoggerInterface {\n    return this._logger\n  }\n  // endregion ////\n\n  async applyOperatingLimits(requestId: string, method: string, params?: any): Promise<void> {\n    // 1. Check operating limit\n    const operatingWait = await this.#operatingLimiter.waitIfNeeded(requestId, method, params)\n    if (operatingWait > 0) {\n      this.incrementStats('limitHits')\n      this.#logMethodBlocked(this.#operatingLimiter.getTitle(), requestId, method, operatingWait)\n      await this.#delay(operatingWait)\n    } else {\n      // 2. Apply adaptive delay\n      const adaptiveDelay = await this.#adaptiveDelayer.waitIfNeeded(requestId, method, params)\n      if (adaptiveDelay > 0) {\n        this.incrementStats('limitHits')\n        this.#logMethodBlocked(this.#adaptiveDelayer.getTitle(), requestId, method, adaptiveDelay)\n        await this.#delay(adaptiveDelay)\n      }\n    }\n  }\n\n  /**\n   * Checks and waits for the rate limit\n   * The loop is needed for parallel requests (Promise.all())\n   */\n  async checkRateLimit(requestId: string, method: string): Promise<void> {\n    // 3. Apply rate limit\n    let waitTime\n    let times = 1\n    do {\n      waitTime = await this.#rateLimiter.waitIfNeeded(requestId, method)\n      if (waitTime > 0) {\n        this.incrementStats('limitHits')\n        this.#logMethodBlockedWithTimes(this.#rateLimiter.getTitle(), requestId, method, waitTime, times)\n        await this.#delay(waitTime)\n        times++\n      }\n    } while (waitTime > 0)\n  }\n\n  async updateStats(\n    requestId: string,\n    method: string,\n    timeData: any\n  ): Promise<void> {\n    await this.#operatingLimiter.updateStats(requestId, method, timeData)\n    await this.#adaptiveDelayer.updateStats(requestId, method, timeData)\n    await this.#rateLimiter.updateStats(requestId, method, timeData)\n  }\n\n  async handleError(\n    requestId: string,\n    method: string,\n    params: any,\n    error: any,\n    attempt: number\n  ): Promise<number> {\n    // Rate limit exceeded\n    if (this.#isRateLimitError(error)) {\n      // Since this is error handling, we take into account the number of attempts\n      const wait = (await this.#handleRateLimitExceeded(requestId)) * Math.pow(1.5, attempt)\n      this.#logError(this.#rateLimiter.getTitle(), requestId, 'QUERY_LIMIT_EXCEEDED', error.message, method, wait)\n      return wait\n    }\n\n    // Operating limit exceeded\n    if (this.#isOperatingLimitError(error)) {\n      // Since this is error handling, we will increase the minimum to 10 seconds.\n      const wait = Math.max(10_000, await this.#handleOperatingLimitError(requestId, method, params, error))\n      this.#logError(this.#operatingLimiter.getTitle(), requestId, 'OPERATION_TIME_LIMIT', error.message, method, wait)\n      return wait\n    }\n\n    // Other exceptions\n    if (!this.#isNeedThrowError(error)) {\n      // Since this is error handling, we take into account the number of attempts\n      const baseDelay = await this.#getErrorBackoff(requestId)\n      const maxDelay = Math.max(30_000, baseDelay)\n      const delay = Math.min(maxDelay, baseDelay * Math.pow(2, attempt))\n\n      // Add jitter to prevent thundering herd\n      const jitter = delay * 0.1 * (Math.random() * 2 - 1) // ±10% jitter\n      const wait = Math.max(100, delay + jitter)\n\n      this.#logSomeError(requestId, error?.code ? `${error.code}` : '?', error.message, method, wait)\n\n      return wait\n    }\n\n    return 0 // We don't repeat\n  }\n\n  /**\n   * Checks if the error is a rate limit\n   */\n  #isRateLimitError(error: any): boolean {\n    return error.status === 503\n      || error.code === 'QUERY_LIMIT_EXCEEDED'\n  }\n\n  /**\n   * Delay when exceeding the rate limit\n   */\n  async #handleRateLimitExceeded(requestId: string): Promise<number> {\n    return this.#rateLimiter.handleExceeded(requestId)\n  }\n\n  /**\n   * Checks if the error is an operating limit\n   *\n   * @memo `OPERATION_TIME_LIMIT` && `429` - obtained through practical means\n   * @memo This doesn't work for `batch` queries.\n   */\n  #isOperatingLimitError(error: any): boolean {\n    return error.status === 429\n      || error.code === 'OPERATION_TIME_LIMIT'\n  }\n\n  /**\n   * Operating limit error delay\n   *\n   * @memo Currently, the errors don't include timings for operations.\n   *       For this reason, we will take data from the previous request\n   */\n  async #handleOperatingLimitError(requestId: string, method: string, params?: any, _error?: any): Promise<number> {\n    return this.#operatingLimiter.getTimeToFree(requestId, method, params, _error)\n  }\n\n  /**\n   * Checks whether attempts should be stopped if errors are encountered that are unclear.\n   */\n  #isNeedThrowError(error: any): boolean {\n    const answerError = {\n      code: error?.code ?? '-1',\n      description: error?.message ?? ''\n    }\n\n    return [\n      ...this.exceptionCodeForHard,\n      ...this.exceptionCodeForSoft\n    ].includes(answerError.code)\n    || (answerError.description ?? '').includes('Could not find value for parameter')\n  }\n\n  /**\n   * These exceptions will be thrown\n   */\n  get exceptionCodeForHard(): string[] {\n    return [\n      'ERR_BAD_REQUEST',\n      'JSSDK_UNKNOWN_ERROR', // 'REQUEST_TIMEOUT', 'NETWORK_ERROR',\n      '100',\n      'INTERNAL_SERVER_ERROR', 'ERROR_UNEXPECTED_ANSWER', 'PORTAL_DELETED',\n      'ERROR_BATCH_METHOD_NOT_ALLOWED', 'ERROR_BATCH_LENGTH_EXCEEDED',\n      'NO_AUTH_FOUND',\n      'INVALID_REQUEST',\n      'OVERLOAD_LIMIT', 'expired_token',\n      'ACCESS_DENIED', 'INVALID_CREDENTIALS', 'user_access_error', 'insufficient_scope',\n      'ERROR_MANIFEST_IS_NOT_AVAILABLE',\n      'allowed_only_intranet_user',\n      'NOT_FOUND',\n      'INVALID_ARG_VALUE'\n    ]\n  }\n\n  /**\n   * These exceptions will be thrown into `AjaxResult` as `AjaxError`\n   */\n  get exceptionCodeForSoft(): string[] {\n    return [\n      'ERROR_ENTITY_NOT_FOUND',\n      'BITRIX_REST_V3_EXCEPTION_ACCESSDENIEDEXCEPTION',\n      'BITRIX_REST_V3_EXCEPTION_INVALIDJSONEXCEPTION',\n      'BITRIX_REST_V3_EXCEPTION_INVALIDFILTEREXCEPTION',\n      'BITRIX_REST_V3_EXCEPTION_INVALIDSELECTEXCEPTION',\n      'BITRIX_REST_V3_EXCEPTION_ENTITYNOTFOUNDEXCEPTION',\n      'BITRIX_REST_V3_EXCEPTION_METHODNOTFOUNDEXCEPTION',\n      'BITRIX_REST_V3_EXCEPTION_UNKNOWNDTOPROPERTYEXCEPTION',\n      'BITRIX_REST_V3_EXCEPTION_VALIDATION_REQUESTVALIDATIONEXCEPTION',\n      'BITRIX_REST_V3_EXCEPTION_VALIDATION_DTOVALIDATIONEXCEPTION'\n    ]\n  }\n\n  /**\n   * Delay due to unknown errors\n   */\n  async #getErrorBackoff(_requestId: string): Promise<number> {\n    return this.#config.retryDelay!\n  }\n\n  incrementError(method: string): void {\n    const current = this.#errorCounts.get(method) || 0\n    this.#errorCounts.set(method, current + 1)\n    this.incrementStats('consecutiveErrors')\n  }\n\n  resetErrors(method: string): void {\n    this.#errorCounts.delete(method)\n    this.#stats.consecutiveErrors = 0\n  }\n\n  incrementStats(stat: keyof Pick<RestrictionManagerStats, 'retries' | 'consecutiveErrors' | 'limitHits'>): void {\n    this.#stats[stat]++\n  }\n\n  /**\n   * Returns job statistics\n   */\n  getStats(): RestrictionManagerStats & {\n    adaptiveDelayAvg: number\n    errorCounts: Record<string, number>\n  } {\n    return {\n      ...this.#stats,\n      ...this.#rateLimiter.getStats(),\n      ...this.#adaptiveDelayer.getStats(),\n      ...this.#operatingLimiter.getStats(),\n      errorCounts: Object.fromEntries(this.#errorCounts)\n    }\n  }\n\n  /**\n   * Resets limiters and statistics\n   */\n  async reset(): Promise<void> {\n    await this.#rateLimiter.reset()\n    await this.#operatingLimiter.reset()\n    await this.#adaptiveDelayer.reset()\n    this.#errorCounts.clear()\n\n    this.#stats = {\n      retries: 0,\n      consecutiveErrors: 0,\n      limitHits: 0\n    }\n  }\n\n  async setConfig(params: RestrictionParams): Promise<void> {\n    this.#config = params\n    await this.#rateLimiter.setConfig(params.rateLimit!)\n    await this.#operatingLimiter.setConfig(params.operatingLimit!)\n    await this.#adaptiveDelayer.setConfig(params.adaptiveConfig!)\n  }\n\n  getParams(): RestrictionParams {\n    return { ...this.#config }\n  }\n\n  /**\n   * Delay function\n   */\n  async #delay(ms: number): Promise<void> {\n    return new Promise(resolve => setTimeout(resolve, ms))\n  }\n\n  /**\n   * Public access to the delay function\n   */\n  async waiteDelay(ms: number): Promise<void> {\n    return this.#delay(ms)\n  }\n\n  // region Log ////\n  #logMethodBlocked(limiter: string, requestId: string, method: string, wait: number) {\n    this.getLogger().notice(`${limiter} blocked method ${method}`, {\n      requestId,\n      method,\n      wait,\n      limiter\n    })\n  }\n\n  #logMethodBlockedWithTimes(limiter: string, requestId: string, method: string, wait: number, times: number) {\n    this.getLogger().notice(`${limiter} blocked method ${method} | ${times} times`, {\n      requestId,\n      method,\n      times,\n      wait,\n      limiter\n    })\n  }\n\n  #logError(limiter: string, requestId: string, code: string, message: string, method: string, wait: number) {\n    this.getLogger().error(`${limiter} recognized the ${code} error for the ${method} method`, {\n      requestId,\n      method,\n      wait,\n      limiter,\n      error: {\n        code,\n        message\n      }\n    })\n  }\n\n  #logSomeError(requestId: string, code: string, message: string, method: string, wait: number) {\n    this.getLogger().error(`recognized the ${code} error for the ${method} method`, {\n      requestId,\n      method,\n      wait,\n      error: {\n        code,\n        message\n      }\n    })\n  }\n  // endregion ////\n}\n"],"names":[],"mappings":"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"}