From d87e87aae8821e86d5cbc71215ce846e880266ba Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Fri, 2 Aug 2024 16:43:52 +0100 Subject: [PATCH] initial implementation of retrySync --- src/ops/{async => }/retry.ts | 54 ++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 14 deletions(-) rename src/ops/{async => }/retry.ts (69%) diff --git a/src/ops/async/retry.ts b/src/ops/retry.ts similarity index 69% rename from src/ops/async/retry.ts rename to src/ops/retry.ts index 9810de2f..c6210578 100644 --- a/src/ops/async/retry.ts +++ b/src/ops/retry.ts @@ -1,6 +1,6 @@ -import {$A, IterationState, Operation} from '../../types'; -import {isPromiseLike} from '../../typeguards'; -import {createOperation, throwOnSync} from '../../utils'; +import {$A, IterationState, Operation} from '../types'; +import {isPromiseLike} from '../typeguards'; +import {createOperation} from '../utils'; /** * When an asynchronous iterable rejects, it retries getting the value specified number of times. @@ -64,19 +64,45 @@ export function retry( ): Operation; export function retry(...args: unknown[]) { - return createOperation(throwOnSync('retry'), retryAsync, args); + return createOperation(retrySync, retryAsync, args); } -function retryAsync( - iterable: AsyncIterable, - retry: - | number - | (( - index: number, - attempts: number, - state: IterationState - ) => boolean | Promise) -): AsyncIterable { +type Retry = number | ((index: number, attempts: number, state: IterationState) => T); + +function retrySync(iterable: Iterable, retry: Retry): Iterable { + return { + [Symbol.iterator](): Iterator { + const i = iterable[Symbol.iterator](); + const state: IterationState = {}; + let index = 0; + const cb = typeof retry === 'function' && retry; + let attempts = 0; + const retriesNumber = !cb && retry > 0 ? retry : 0; + let leftTries = retriesNumber; + return { + next(): IteratorResult { + do { + try { + const a = i.next(); + index++; + attempts = 0; + leftTries = retriesNumber; + return a; + } catch (err) { + const r = cb && cb(index, attempts++, state); + if (r || leftTries--) { + continue; + } + throw err; // out of attempts, re-throw + } + } while (true); + } + }; + } + }; +} + +function retryAsync(iterable: AsyncIterable, retry: Retry>): AsyncIterable { return { [$A](): AsyncIterator { const i = iterable[$A]();