aboutsummaryrefslogtreecommitdiffstats
path: root/node_modules/exponential-backoff/src/backoff.ts
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--node_modules/exponential-backoff/src/backoff.ts60
1 files changed, 60 insertions, 0 deletions
diff --git a/node_modules/exponential-backoff/src/backoff.ts b/node_modules/exponential-backoff/src/backoff.ts
new file mode 100644
index 0000000..549770b
--- /dev/null
+++ b/node_modules/exponential-backoff/src/backoff.ts
@@ -0,0 +1,60 @@
+import {
+ IBackOffOptions,
+ getSanitizedOptions,
+ BackoffOptions
+} from "./options";
+import { DelayFactory } from "./delay/delay.factory";
+
+export { BackoffOptions, IBackOffOptions };
+
+/**
+ * Executes a function with exponential backoff.
+ * @param request the function to be executed
+ * @param options options to customize the backoff behavior
+ * @returns Promise that resolves to the result of the `request` function
+ */
+export async function backOff<T>(
+ request: () => Promise<T>,
+ options: BackoffOptions = {}
+): Promise<T> {
+ const sanitizedOptions = getSanitizedOptions(options);
+ const backOff = new BackOff(request, sanitizedOptions);
+
+ return await backOff.execute();
+}
+
+class BackOff<T> {
+ private attemptNumber = 0;
+
+ constructor(
+ private request: () => Promise<T>,
+ private options: IBackOffOptions
+ ) {}
+
+ public async execute(): Promise<T> {
+ while (!this.attemptLimitReached) {
+ try {
+ await this.applyDelay();
+ return await this.request();
+ } catch (e) {
+ this.attemptNumber++;
+ const shouldRetry = await this.options.retry(e, this.attemptNumber);
+
+ if (!shouldRetry || this.attemptLimitReached) {
+ throw e;
+ }
+ }
+ }
+
+ throw new Error("Something went wrong.");
+ }
+
+ private get attemptLimitReached() {
+ return this.attemptNumber >= this.options.numOfAttempts;
+ }
+
+ private async applyDelay() {
+ const delay = DelayFactory(this.options, this.attemptNumber);
+ await delay.apply();
+ }
+}