summaryrefslogtreecommitdiff
path: root/src/lib/utils/retry.ts
diff options
context:
space:
mode:
authorElizabeth Hunt <elizabeth.hunt@simponic.xyz>2024-01-07 01:21:06 -0700
committerElizabeth Hunt <elizabeth.hunt@simponic.xyz>2024-01-07 01:21:06 -0700
commitdb671d26c43e47b8285d319a0fd758df60d729c7 (patch)
tree4cfc7e7b719d246637818e83feb8981255c19c67 /src/lib/utils/retry.ts
parente1905622d7d8657aa7cd5bdfe9d06e4fbe40dc70 (diff)
downloadmistymountainstherapy-db671d26c43e47b8285d319a0fd758df60d729c7.tar.gz
mistymountainstherapy-db671d26c43e47b8285d319a0fd758df60d729c7.zip
initial update with nodemailer
Diffstat (limited to 'src/lib/utils/retry.ts')
-rw-r--r--src/lib/utils/retry.ts45
1 files changed, 45 insertions, 0 deletions
diff --git a/src/lib/utils/retry.ts b/src/lib/utils/retry.ts
new file mode 100644
index 0000000..34bc73b
--- /dev/null
+++ b/src/lib/utils/retry.ts
@@ -0,0 +1,45 @@
+export type RetryStrategyF = (retries: number) => number;
+
+export const MAX_DEFAULT_RETRY_AMOUNT = 5;
+export const WAIT_MS = 1_000;
+export const RETRY_EXPONENT = 2;
+export const RETRY_EXPONENTIAL_FACTOR = 1.1;
+export const RETRY_JITTER_MAX = 3_000;
+
+const waitFor = (ms: number) => new Promise((res) => setTimeout(res, ms));
+
+const exponentialStrategyWithJitter: RetryStrategyF = (retries: number) =>
+ WAIT_MS * Math.pow(RETRY_EXPONENT, RETRY_EXPONENTIAL_FACTOR * retries) +
+ RETRY_JITTER_MAX * Math.random();
+
+export const continueRetryUntilValidation = async <T>(
+ promiseFn: () => Promise<T> | T | Promise<void> | void,
+ validationFn: (x: T) => Promise<boolean> | boolean = (x: T) =>
+ Promise.resolve(!!x),
+ maxRetries = MAX_DEFAULT_RETRY_AMOUNT,
+ waitTimeStrategy: RetryStrategyF = exponentialStrategyWithJitter,
+ retries = 0,
+ lastError: undefined | unknown = undefined
+): Promise<T> => {
+ if (retries >= maxRetries) {
+ if (lastError) throw lastError;
+ throw new Error("Exceeded maximum retry amount");
+ }
+ try {
+ if (retries) await waitFor(waitTimeStrategy(retries));
+
+ const res = await promiseFn();
+ if (res && (await validationFn(res))) return res;
+
+ throw new Error("Validation predicate unsuccessful");
+ } catch (e: unknown) {
+ return continueRetryUntilValidation(
+ promiseFn,
+ validationFn,
+ maxRetries,
+ waitTimeStrategy,
+ retries + 1,
+ e
+ );
+ }
+}; \ No newline at end of file