UNPKG

@langchain/core

Version:
1 lines 8.44 kB
{"version":3,"file":"async_caller.cjs","names":["error: unknown","params: AsyncCallerParams","PQueueMod","callable: T","pRetry","options: AsyncCallerCallOptions","listener: (() => void) | undefined","getAbortSignalError"],"sources":["../../src/utils/async_caller.ts"],"sourcesContent":["import PQueueMod from \"p-queue\";\n\nimport { getAbortSignalError } from \"./signal.js\";\nimport pRetry from \"./p-retry/index.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/**\n * The default failed attempt handler for the AsyncCaller.\n * @param error - The error to handle.\n * @returns void\n */\nconst defaultFailedAttemptHandler = (error: unknown) => {\n if (typeof error !== \"object\" || error === null) {\n return;\n }\n\n if (\n (\"message\" in error &&\n typeof error.message === \"string\" &&\n (error.message.startsWith(\"Cancel\") ||\n error.message.startsWith(\"AbortError\"))) ||\n (\"name\" in error &&\n typeof error.name === \"string\" &&\n error.name === \"AbortError\")\n ) {\n throw error;\n }\n if (\n \"code\" in error &&\n typeof error.code === \"string\" &&\n error.code === \"ECONNABORTED\"\n ) {\n throw error;\n }\n const status =\n \"response\" in error &&\n typeof error.response === \"object\" &&\n error.response !== null &&\n \"status\" in error.response &&\n typeof error.response.status === \"number\"\n ? error.response.status\n : undefined;\n if (status && STATUS_NO_RETRY.includes(+status)) {\n throw error;\n }\n\n const code =\n \"error\" in error &&\n typeof error.error === \"object\" &&\n error.error !== null &&\n \"code\" in error.error &&\n typeof error.error.code === \"string\"\n ? error.error.code\n : undefined;\n if (code === \"insufficient_quota\") {\n const err = new Error(\n \"message\" in error && typeof error.message === \"string\"\n ? error.message\n : \"Insufficient quota\"\n );\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 async 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: ({ error }) => this.onFailedAttempt?.(error),\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;;;;;;AAOD,MAAM,8BAA8B,CAACA,UAAmB;AACtD,KAAI,OAAO,UAAU,YAAY,UAAU,KACzC;AAGF,KACG,aAAa,SACZ,OAAO,MAAM,YAAY,aACxB,MAAM,QAAQ,WAAW,SAAS,IACjC,MAAM,QAAQ,WAAW,aAAa,KACzC,UAAU,SACT,OAAO,MAAM,SAAS,YACtB,MAAM,SAAS,aAEjB,OAAM;AAER,KACE,UAAU,SACV,OAAO,MAAM,SAAS,YACtB,MAAM,SAAS,eAEf,OAAM;CAER,MAAM,SACJ,cAAc,SACd,OAAO,MAAM,aAAa,YAC1B,MAAM,aAAa,QACnB,YAAY,MAAM,YAClB,OAAO,MAAM,SAAS,WAAW,WAC7B,MAAM,SAAS,SACf;AACN,KAAI,UAAU,gBAAgB,SAAS,CAAC,OAAO,CAC7C,OAAM;CAGR,MAAM,OACJ,WAAW,SACX,OAAO,MAAM,UAAU,YACvB,MAAM,UAAU,QAChB,UAAU,MAAM,SAChB,OAAO,MAAM,MAAM,SAAS,WACxB,MAAM,MAAM,OACZ;AACN,KAAI,SAAS,sBAAsB;EACjC,MAAM,MAAM,IAAI,MACd,aAAa,SAAS,OAAO,MAAM,YAAY,WAC3C,MAAM,UACN;EAEN,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,MAAM,KACJC,UACA,GAAG,MAC8B;AACjC,SAAO,KAAK,MAAM,IAChB,MACEC,qBACE,MACE,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,UAAU;AAEjC,OAAI,iBAAiB,MACnB,OAAM;OAEN,OAAM,IAAI,MAAM;EAEnB,EAAC,EACJ;GACE,iBAAiB,CAAC,EAAE,OAAO,KAAK,KAAK,kBAAkB,MAAM;GAC7D,SAAS,KAAK;GACd,WAAW;EAGZ,EACF,EACH,EAAE,gBAAgB,KAAM,EACzB;CACF;CAGD,gBACEC,SACAF,UACA,GAAG,MAC8B;AAGjC,MAAI,QAAQ,QAAQ;GAClB,IAAIG;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"}