{"version":3,"file":"async_caller.cjs","names":["error: any","params: AsyncCallerParams","PQueueMod","callable: T","options: AsyncCallerCallOptions","listener: (() => void) | undefined","getAbortSignalError"],"sources":["../../src/utils/async_caller.ts"],"sourcesContent":["import pRetry from \"p-retry\";\nimport PQueueMod from \"p-queue\";\n\nimport { getAbortSignalError } from \"./signal.js\";\n\nconst STATUS_NO_RETRY = [\n  400, // Bad Request\n  401, // Unauthorized\n  402, // Payment Required\n  403, // Forbidden\n  404, // Not Found\n  405, // Method Not Allowed\n  406, // Not Acceptable\n  407, // Proxy Authentication Required\n  409, // Conflict\n];\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst defaultFailedAttemptHandler = (error: any) => {\n  if (\n    error.message.startsWith(\"Cancel\") ||\n    error.message.startsWith(\"AbortError\") ||\n    error.name === \"AbortError\"\n  ) {\n    throw error;\n  }\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  if ((error as any)?.code === \"ECONNABORTED\") {\n    throw error;\n  }\n  const status =\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    (error as any)?.response?.status ?? (error as any)?.status;\n  if (status && STATUS_NO_RETRY.includes(+status)) {\n    throw error;\n  }\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  if ((error as any)?.error?.code === \"insufficient_quota\") {\n    const err = new Error(error?.message);\n    err.name = \"InsufficientQuotaError\";\n    throw err;\n  }\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type FailedAttemptHandler = (error: any) => any;\n\nexport interface AsyncCallerParams {\n  /**\n   * The maximum number of concurrent calls that can be made.\n   * Defaults to `Infinity`, which means no limit.\n   */\n  maxConcurrency?: number;\n  /**\n   * The maximum number of retries that can be made for a single call,\n   * with an exponential backoff between each attempt. Defaults to 6.\n   */\n  maxRetries?: number;\n  /**\n   * Custom handler to handle failed attempts. Takes the originally thrown\n   * error object as input, and should itself throw an error if the input\n   * error is not retryable.\n   */\n  onFailedAttempt?: FailedAttemptHandler;\n}\n\nexport interface AsyncCallerCallOptions {\n  signal?: AbortSignal;\n}\n\n/**\n * A class that can be used to make async calls with concurrency and retry logic.\n *\n * This is useful for making calls to any kind of \"expensive\" external resource,\n * be it because it's rate-limited, subject to network issues, etc.\n *\n * Concurrent calls are limited by the `maxConcurrency` parameter, which defaults\n * to `Infinity`. This means that by default, all calls will be made in parallel.\n *\n * Retries are limited by the `maxRetries` parameter, which defaults to 6. This\n * means that by default, each call will be retried up to 6 times, with an\n * exponential backoff between each attempt.\n */\nexport class AsyncCaller {\n  protected maxConcurrency: AsyncCallerParams[\"maxConcurrency\"];\n\n  protected maxRetries: AsyncCallerParams[\"maxRetries\"];\n\n  protected onFailedAttempt: AsyncCallerParams[\"onFailedAttempt\"];\n\n  private queue: typeof import(\"p-queue\")[\"default\"][\"prototype\"];\n\n  constructor(params: AsyncCallerParams) {\n    this.maxConcurrency = params.maxConcurrency ?? Infinity;\n    this.maxRetries = params.maxRetries ?? 6;\n    this.onFailedAttempt =\n      params.onFailedAttempt ?? defaultFailedAttemptHandler;\n\n    const PQueue = (\n      \"default\" in PQueueMod ? PQueueMod.default : PQueueMod\n    ) as typeof PQueueMod;\n    this.queue = new PQueue({ concurrency: this.maxConcurrency });\n  }\n\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  call<A extends any[], T extends (...args: A) => Promise<any>>(\n    callable: T,\n    ...args: Parameters<T>\n  ): Promise<Awaited<ReturnType<T>>> {\n    return this.queue.add(\n      () =>\n        pRetry(\n          () =>\n            callable(...args).catch((error) => {\n              // eslint-disable-next-line no-instanceof/no-instanceof\n              if (error instanceof Error) {\n                throw error;\n              } else {\n                throw new Error(error);\n              }\n            }),\n          {\n            onFailedAttempt: this.onFailedAttempt,\n            retries: this.maxRetries,\n            randomize: true,\n            // If needed we can change some of the defaults here,\n            // but they're quite sensible.\n          }\n        ),\n      { throwOnTimeout: true }\n    );\n  }\n\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  callWithOptions<A extends any[], T extends (...args: A) => Promise<any>>(\n    options: AsyncCallerCallOptions,\n    callable: T,\n    ...args: Parameters<T>\n  ): Promise<Awaited<ReturnType<T>>> {\n    // Note this doesn't cancel the underlying request,\n    // when available prefer to use the signal option of the underlying call\n    if (options.signal) {\n      let listener: (() => void) | undefined;\n      return Promise.race([\n        this.call<A, T>(callable, ...args),\n        new Promise<never>((_, reject) => {\n          listener = () => {\n            reject(getAbortSignalError(options.signal));\n          };\n          options.signal?.addEventListener(\"abort\", listener);\n        }),\n      ]).finally(() => {\n        if (options.signal && listener) {\n          options.signal.removeEventListener(\"abort\", listener);\n        }\n      });\n    }\n    return this.call<A, T>(callable, ...args);\n  }\n\n  fetch(...args: Parameters<typeof fetch>): ReturnType<typeof fetch> {\n    return this.call(() =>\n      fetch(...args).then((res) => (res.ok ? res : Promise.reject(res)))\n    );\n  }\n}\n"],"mappings":";;;;;;;;AAKA,MAAM,kBAAkB;CACtB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACD;AAGD,MAAM,8BAA8B,CAACA,UAAe;AAClD,KACE,MAAM,QAAQ,WAAW,SAAS,IAClC,MAAM,QAAQ,WAAW,aAAa,IACtC,MAAM,SAAS,aAEf,OAAM;AAGR,KAAK,OAAe,SAAS,eAC3B,OAAM;CAER,MAAM,SAEH,OAAe,UAAU,UAAW,OAAe;AACtD,KAAI,UAAU,gBAAgB,SAAS,CAAC,OAAO,CAC7C,OAAM;AAGR,KAAK,OAAe,OAAO,SAAS,sBAAsB;EACxD,MAAM,MAAM,IAAI,MAAM,OAAO;EAC7B,IAAI,OAAO;AACX,QAAM;CACP;AACF;;;;;;;;;;;;;;AAyCD,IAAa,cAAb,MAAyB;CACvB,AAAU;CAEV,AAAU;CAEV,AAAU;CAEV,AAAQ;CAER,YAAYC,QAA2B;EACrC,KAAK,iBAAiB,OAAO,kBAAkB;EAC/C,KAAK,aAAa,OAAO,cAAc;EACvC,KAAK,kBACH,OAAO,mBAAmB;EAE5B,MAAM,SACJ,aAAaC,kBAAYA,gBAAU,UAAUA;EAE/C,KAAK,QAAQ,IAAI,OAAO,EAAE,aAAa,KAAK,eAAgB;CAC7D;CAGD,KACEC,UACA,GAAG,MAC8B;AACjC,SAAO,KAAK,MAAM,IAChB,2BAEI,MACE,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,UAAU;AAEjC,OAAI,iBAAiB,MACnB,OAAM;OAEN,OAAM,IAAI,MAAM;EAEnB,EAAC,EACJ;GACE,iBAAiB,KAAK;GACtB,SAAS,KAAK;GACd,WAAW;EAGZ,EACF,EACH,EAAE,gBAAgB,KAAM,EACzB;CACF;CAGD,gBACEC,SACAD,UACA,GAAG,MAC8B;AAGjC,MAAI,QAAQ,QAAQ;GAClB,IAAIE;AACJ,UAAO,QAAQ,KAAK,CAClB,KAAK,KAAW,UAAU,GAAG,KAAK,EAClC,IAAI,QAAe,CAAC,GAAG,WAAW;IAChC,WAAW,MAAM;KACf,OAAOC,mCAAoB,QAAQ,OAAO,CAAC;IAC5C;IACD,QAAQ,QAAQ,iBAAiB,SAAS,SAAS;GACpD,EACF,EAAC,CAAC,QAAQ,MAAM;AACf,QAAI,QAAQ,UAAU,UACpB,QAAQ,OAAO,oBAAoB,SAAS,SAAS;GAExD,EAAC;EACH;AACD,SAAO,KAAK,KAAW,UAAU,GAAG,KAAK;CAC1C;CAED,MAAM,GAAG,MAA0D;AACjE,SAAO,KAAK,KAAK,MACf,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,QAAS,IAAI,KAAK,MAAM,QAAQ,OAAO,IAAI,CAAE,CACnE;CACF;AACF"}