feat: add retry to accounting (#166)
* feat: add retry to accounting * fix: fix off by one bug in retry logic * docs: add jsdocs to new utility functions * style: rename DepositModal to CheckoutModal
This commit is contained in:
@@ -32,3 +32,77 @@ export function makeBigNumber(value: BigNumber | BigInt | number | string): BigN
|
||||
|
||||
throw new TypeError(`Not a BigNumber or BigNumber convertible value. Type: ${typeof value} value: ${value}`)
|
||||
}
|
||||
|
||||
export type PromiseSettlements<T> = {
|
||||
fulfilled: PromiseFulfilledResult<T>[]
|
||||
rejected: PromiseRejectedResult[]
|
||||
}
|
||||
|
||||
export type UnwrappedPromiseSettlements<T> = {
|
||||
fulfilled: T[]
|
||||
rejected: string[]
|
||||
}
|
||||
|
||||
export async function sleepMs(ms: number): Promise<void> {
|
||||
await new Promise<void>(resolve =>
|
||||
setTimeout(() => {
|
||||
resolve()
|
||||
}, ms),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the returned results of `Promise.allSettled` to an object
|
||||
* with `fulfilled` and `rejected` arrays for easy access.
|
||||
*
|
||||
* The results still need to be unwrapped to get the fulfilled values or rejection reasons.
|
||||
*/
|
||||
export function mapPromiseSettlements<T>(promises: PromiseSettledResult<T>[]): PromiseSettlements<T> {
|
||||
const fulfilled = promises.filter(promise => promise.status === 'fulfilled') as PromiseFulfilledResult<T>[]
|
||||
const rejected = promises.filter(promise => promise.status === 'rejected') as PromiseRejectedResult[]
|
||||
|
||||
return { fulfilled, rejected }
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the returned values of `Promise.allSettled` to an object
|
||||
* with `fulfilled` and `rejected` arrays for easy access.
|
||||
*
|
||||
* For rejected promises, the value is the stringified `reason`,
|
||||
* or `'Unknown error'` string when it is unavailable.
|
||||
*/
|
||||
export function unwrapPromiseSettlements<T>(
|
||||
promiseSettledResults: PromiseSettledResult<T>[],
|
||||
): UnwrappedPromiseSettlements<T> {
|
||||
const values = mapPromiseSettlements(promiseSettledResults)
|
||||
const fulfilled = values.fulfilled.map(x => x.value)
|
||||
const rejected = values.rejected.map(x => (x.reason ? String(x.reason) : 'Unknown error'))
|
||||
|
||||
return { fulfilled, rejected }
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a `Promise<T>` or async function inside a new `Promise<T>`,
|
||||
* which retries the original function up to `maxRetries` times,
|
||||
* waiting `delayMs` milliseconds between failed attempts.
|
||||
*
|
||||
* If all attempts fail, then this `Promise<T>` also rejects.
|
||||
*/
|
||||
export function makeRetriablePromise<T>(fn: () => Promise<T>, maxRetries = 3, delayMs = 1000): Promise<T> {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
for (let tries = 0; tries < maxRetries; tries++) {
|
||||
try {
|
||||
const results = await fn()
|
||||
resolve(results)
|
||||
|
||||
return
|
||||
} catch (error) {
|
||||
if (tries < maxRetries - 1) {
|
||||
await sleepMs(delayMs)
|
||||
} else {
|
||||
reject(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user