abort-controller-x
Advanced tools
Comparing version 0.2.6 to 0.2.7
@@ -36,3 +36,7 @@ import { AbortSignal } from 'node-abort-controller'; | ||
* Retry function with exponential backoff. | ||
* | ||
* The function receives AbortSignal, attempt number starting with 0, and reset | ||
* function that sets attempt number to -1 so that the next attempt will be | ||
* made without delay. | ||
*/ | ||
export declare function retry<T>(signal: AbortSignal, fn: (signal: AbortSignal, attempt: number) => Promise<T>, options?: RetryOptions): Promise<T>; | ||
export declare function retry<T>(signal: AbortSignal, fn: (signal: AbortSignal, attempt: number, reset: () => void) => Promise<T>, options?: RetryOptions): Promise<T>; |
@@ -5,8 +5,16 @@ import { delay } from './delay'; | ||
* Retry function with exponential backoff. | ||
* | ||
* The function receives AbortSignal, attempt number starting with 0, and reset | ||
* function that sets attempt number to -1 so that the next attempt will be | ||
* made without delay. | ||
*/ | ||
export async function retry(signal, fn, options = {}) { | ||
const { baseMs = 1000, maxDelayMs = 15000, onError, maxAttempts = Infinity, } = options; | ||
for (let attempt = 0;; attempt++) { | ||
let attempt = 0; | ||
const reset = () => { | ||
attempt = -1; | ||
}; | ||
while (true) { | ||
try { | ||
return await fn(signal, attempt); | ||
return await fn(signal, attempt, reset); | ||
} | ||
@@ -18,9 +26,18 @@ catch (error) { | ||
} | ||
// https://aws.amazon.com/ru/blogs/architecture/exponential-backoff-and-jitter/ | ||
const backoff = Math.min(maxDelayMs, Math.pow(2, attempt) * baseMs); | ||
const delayMs = Math.round((backoff * (1 + Math.random())) / 2); | ||
let delayMs; | ||
if (attempt === -1) { | ||
delayMs = 0; | ||
} | ||
else { | ||
// https://aws.amazon.com/ru/blogs/architecture/exponential-backoff-and-jitter/ | ||
const backoff = Math.min(maxDelayMs, Math.pow(2, attempt) * baseMs); | ||
delayMs = Math.round((backoff * (1 + Math.random())) / 2); | ||
} | ||
if (onError) { | ||
onError(error, attempt, delayMs); | ||
} | ||
await delay(signal, delayMs); | ||
if (delayMs !== 0) { | ||
await delay(signal, delayMs); | ||
} | ||
attempt += 1; | ||
} | ||
@@ -27,0 +44,0 @@ } |
@@ -36,3 +36,7 @@ import { AbortSignal } from 'node-abort-controller'; | ||
* Retry function with exponential backoff. | ||
* | ||
* The function receives AbortSignal, attempt number starting with 0, and reset | ||
* function that sets attempt number to -1 so that the next attempt will be | ||
* made without delay. | ||
*/ | ||
export declare function retry<T>(signal: AbortSignal, fn: (signal: AbortSignal, attempt: number) => Promise<T>, options?: RetryOptions): Promise<T>; | ||
export declare function retry<T>(signal: AbortSignal, fn: (signal: AbortSignal, attempt: number, reset: () => void) => Promise<T>, options?: RetryOptions): Promise<T>; |
@@ -8,8 +8,16 @@ "use strict"; | ||
* Retry function with exponential backoff. | ||
* | ||
* The function receives AbortSignal, attempt number starting with 0, and reset | ||
* function that sets attempt number to -1 so that the next attempt will be | ||
* made without delay. | ||
*/ | ||
async function retry(signal, fn, options = {}) { | ||
const { baseMs = 1000, maxDelayMs = 15000, onError, maxAttempts = Infinity, } = options; | ||
for (let attempt = 0;; attempt++) { | ||
let attempt = 0; | ||
const reset = () => { | ||
attempt = -1; | ||
}; | ||
while (true) { | ||
try { | ||
return await fn(signal, attempt); | ||
return await fn(signal, attempt, reset); | ||
} | ||
@@ -21,9 +29,18 @@ catch (error) { | ||
} | ||
// https://aws.amazon.com/ru/blogs/architecture/exponential-backoff-and-jitter/ | ||
const backoff = Math.min(maxDelayMs, Math.pow(2, attempt) * baseMs); | ||
const delayMs = Math.round((backoff * (1 + Math.random())) / 2); | ||
let delayMs; | ||
if (attempt === -1) { | ||
delayMs = 0; | ||
} | ||
else { | ||
// https://aws.amazon.com/ru/blogs/architecture/exponential-backoff-and-jitter/ | ||
const backoff = Math.min(maxDelayMs, Math.pow(2, attempt) * baseMs); | ||
delayMs = Math.round((backoff * (1 + Math.random())) / 2); | ||
} | ||
if (onError) { | ||
onError(error, attempt, delayMs); | ||
} | ||
await delay_1.delay(signal, delayMs); | ||
if (delayMs !== 0) { | ||
await delay_1.delay(signal, delayMs); | ||
} | ||
attempt += 1; | ||
} | ||
@@ -30,0 +47,0 @@ } |
{ | ||
"name": "abort-controller-x", | ||
"version": "0.2.6", | ||
"version": "0.2.7", | ||
"description": "Abortable async function helpers", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -1,7 +0,5 @@ | ||
# Abort Controller Extras [![npm version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] | ||
# Abort Controller Extras [![npm version][npm-image]][npm-url] | ||
Abortable async function helpers. | ||
Abortable async function primitives and combinators. | ||
<!-- TOC depthFrom:2 depthTo:4 --> | ||
- [Installation](#installation) | ||
@@ -11,2 +9,3 @@ - [Abort Controller](#abort-controller) | ||
- [Composing Abortable Functions](#composing-abortable-functions) | ||
- [Companion Packages](#companion-packages) | ||
- [API](#api) | ||
@@ -29,6 +28,2 @@ - [`all`](#all) | ||
<!-- /TOC --> | ||
<!-- Generated by Markdown TOC --> | ||
<!-- https://marketplace.visualstudio.com/items?itemName=AlanWalk.markdown-toc --> | ||
## Installation | ||
@@ -103,2 +98,7 @@ | ||
## Companion Packages | ||
- [`abort-controller-x-rxjs`](https://github.com/deeplay-io/abort-controller-x-rxjs) | ||
— Abortable helpers for RxJS. | ||
## API | ||
@@ -392,3 +392,3 @@ | ||
signal: AbortSignal, | ||
fn: (signal: AbortSignal, attempt: number) => Promise<T>, | ||
fn: (signal: AbortSignal, attempt: number, reset: () => void) => Promise<T>, | ||
options?: RetryOptions, | ||
@@ -401,3 +401,3 @@ ): Promise<T>; | ||
maxAttempts?: number; | ||
onError?: (error: any, attempt: number, delayMs: number) => void; | ||
onError?: (error: unknown, attempt: number, delayMs: number) => void; | ||
}; | ||
@@ -408,2 +408,19 @@ ``` | ||
- `fn` | ||
A function that will be called and retried in case of error. It receives: | ||
- `signal` | ||
`AbortSignal` that is aborted when the signal passed to `retry` is aborted. | ||
- `attempt` | ||
Attempt number starting with 0. | ||
- `reset` | ||
Function that sets attempt number to -1 so that the next attempt will be | ||
made without delay. | ||
- `RetryOptions.baseMs` | ||
@@ -584,4 +601,1 @@ | ||
[npm-url]: https://badge.fury.io/js/abort-controller-x | ||
[travis-image]: | ||
https://travis-ci.org/deeplay-io/abort-controller-x.svg?branch=master | ||
[travis-url]: https://travis-ci.org/deeplay-io/abort-controller-x |
@@ -40,6 +40,10 @@ import {AbortSignal} from 'node-abort-controller'; | ||
* Retry function with exponential backoff. | ||
* | ||
* The function receives AbortSignal, attempt number starting with 0, and reset | ||
* function that sets attempt number to -1 so that the next attempt will be | ||
* made without delay. | ||
*/ | ||
export async function retry<T>( | ||
signal: AbortSignal, | ||
fn: (signal: AbortSignal, attempt: number) => Promise<T>, | ||
fn: (signal: AbortSignal, attempt: number, reset: () => void) => Promise<T>, | ||
options: RetryOptions = {}, | ||
@@ -54,5 +58,11 @@ ): Promise<T> { | ||
for (let attempt = 0; ; attempt++) { | ||
let attempt = 0; | ||
const reset = () => { | ||
attempt = -1; | ||
}; | ||
while (true) { | ||
try { | ||
return await fn(signal, attempt); | ||
return await fn(signal, attempt, reset); | ||
} catch (error) { | ||
@@ -65,6 +75,12 @@ rethrowAbortError(error); | ||
// https://aws.amazon.com/ru/blogs/architecture/exponential-backoff-and-jitter/ | ||
const backoff = Math.min(maxDelayMs, Math.pow(2, attempt) * baseMs); | ||
const delayMs = Math.round((backoff * (1 + Math.random())) / 2); | ||
let delayMs: number; | ||
if (attempt === -1) { | ||
delayMs = 0; | ||
} else { | ||
// https://aws.amazon.com/ru/blogs/architecture/exponential-backoff-and-jitter/ | ||
const backoff = Math.min(maxDelayMs, Math.pow(2, attempt) * baseMs); | ||
delayMs = Math.round((backoff * (1 + Math.random())) / 2); | ||
} | ||
if (onError) { | ||
@@ -74,5 +90,9 @@ onError(error, attempt, delayMs); | ||
await delay(signal, delayMs); | ||
if (delayMs !== 0) { | ||
await delay(signal, delayMs); | ||
} | ||
attempt += 1; | ||
} | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
178295
4166
595