https://github.com/avivbens/rx-retry
Provide handling for Observables AND Promises retries, with a configurable delay between retries (support JITTER).
https://github.com/avivbens/rx-retry
Last synced: 3 months ago
JSON representation
Provide handling for Observables AND Promises retries, with a configurable delay between retries (support JITTER).
- Host: GitHub
- URL: https://github.com/avivbens/rx-retry
- Owner: Avivbens
- License: mit
- Created: 2022-04-19T23:45:41.000Z (about 3 years ago)
- Default Branch: master
- Last Pushed: 2024-08-31T04:03:23.000Z (9 months ago)
- Last Synced: 2025-03-17T19:21:23.907Z (3 months ago)
- Language: TypeScript
- Homepage:
- Size: 1.41 MB
- Stars: 8
- Watchers: 1
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Security: SECURITY.md
Awesome Lists containing this project
README
RX-Retry for JS and TS, using RxJS, support for Node.js & NestJS and browsers## Has default configuration of random-backoff retry and backoff retry
Read this article for more details:
[AWS Exponential Backoff and Jitter](https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/)
### Provide handling for Observables AND Promises retries, with a configurable delay between retries.
## Installation
```bash
npm i rx-retry
```## Usage
```typescript
import { resolveWithRetry, ResolveRetryConfig, retryBackoff } from 'rx-retry'
import { throwError } from 'rxjs'// Use on a promise
;(() => {
const prm = new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('Promise error'))
}, 1000)
})const configuration: ResolveRetryConfig = {
timeoutTime: 5000, // set timeout to fail the promise and retry, default is 0
useJitter: true, // backoff strategy with random + exponantial delay, default is true
retryStrategy: {
initialInterval: 1000, // ms
maxRetries: 3,
onRetry: (attempt: number, error: Error) => {
console.log('Log this - retry') // adding action on retry
},
maxInterval: 10000, // ms
shouldRetry: (error) => true, // check if retry needed, default is always true
},
}
const res = await resolveWithRetry(prm, configuration)
})()// Use on Observable, will be converted into promise
;(() => {
const obs = throwError('Observable error')const configuration: ResolveRetryConfig = {
timeoutTime: 5000, // set timeout to fail the promise and retry, default is 0
useJitter: true, // backoff strategy with random + exponantial delay, default is true
retryStrategy: {
initialInterval: 1000, // ms
maxRetries: 3,
onRetry: (attempt: number, error: Error) => {
console.log('Log this - retry') // adding action on retry
},
maxInterval: 10000, // ms
shouldRetry: (error) => true, // check if retry needed, default is always true
},
}
const res = await resolveWithRetry(obs, configuration)
})()// Using the custom operator function in a pipe
;(() => {
const obs = throwError('Observable error')obs.pipe(
retryBackoff({
initialInterval: 1000,
maxInterval: 10000,
maxRetries: 5,
}),
)
})()
```
# Out of the box support for NestJS
### Module sync configuration
```typescript
import { Module } from '@nestjs/common'
import { TestingService } from './testing.service'
import { RxRetryModule } from 'rx-retry'@Module({
imports: [
RxRetryModule.register({
timeoutTime: 5000, // set timeout to fail the promise and retry, default is 0
useJitter: true, // backoff strategy with random + exponantial delay, default is true
retryStrategy: {
initialInterval: 1000, // ms
maxRetries: 3,
maxInterval: 10000, // ms
shouldRetry: (error) => true, // check if retry needed, default is always true
},
isGlobal: true, // set module as global
}),
],
providers: [TestingService],
})
export class TestingModule {}
```
### Module async configuration
```typescript
import { Module } from '@nestjs/common'
import { ConfigModule, ConfigService } from '@nestjs/config'
import { TestingService } from './testing.service'
import { RxRetryModule } from 'rx-retry'@Module({
imports: [
// setup for config module
ConfigModule.forRoot({
isGlobal: true,
cache: true,
}),RxRetryModule.registerAsync({
inject: [ConfigService],
isGlobal: true, // set module as global
useFactory: async (conf: ConfigService) => {
const configuration = {
timeoutTime: +conf.get('timeoutTime'), // set timeout to fail the promise and retry, default is 0
useJitter: !!conf.get('useJitter'), // backoff strategy with random + exponantial delay, default is true
retryStrategy: {
initialInterval: +conf.get('initialInterval'), // ms
maxRetries: +conf.get('maxRetries'),
maxInterval: 10000, // ms
},
}return configuration
},
}),
],
providers: [TestingService],
})
export class TestingModule {}
```
### Service usage
```typescript
import { Injectable } from '@nestjs/common'
import { RxRetryService } from 'rx-retry'
import { catchError, from, Observable, of, throwError } from 'rxjs'@Injectable()
export class TestingService {
constructor(private readonly rxRetry: RxRetryService) {}public resolveWithRetry() {
return this.rxRetry.resolveWithRetry(this._getPromise())
}// run over only for loggerInstance, passing it to log with it
public runOverConfiguration() {
return this.rxRetry.resolveWithRetry(this._getPromise(), {
retryStrategy: {
onRetry: (attempt: number, error: Error) => {
this.logger.log(`Retry attempt ${attempt}`)
},
},
})
}// Resolve Obsevable into promise with global config
public resolveWithRetryObs() {
return this.rxRetry.resolveWithRetry(this._getObs())
}// Using the basic operator
public resolveWithRetryObsPipe() {
return this._getObs().pipe(
retryBackoff({
initialInterval: 1000,
maxInterval: 10000,
maxRetries: 5,
onRetry: (attempt: number, error: Error) => {
console.log('attempt :>> ', attempt)
},
}),
)
}// Run over part of the main configuration
public resolveWithRetryObsGlobal() {
return this._getObs().pipe(
this.rxRetry.resolveWithRetryOperator({
initialInterval: 1000,
onRetry: (attempt: number, error: Error) => {
this.logger.debug('attempt :>> ', attempt)
},
}),
)
}private _getObs() {
return throwError('Observable error')
}private _getPromise() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const isOk = Math.random() > 0.5
if (isOk) {
resolve('Promise resolved')
return
}
reject('Promise rejected')
}, 1000)
})
}
}
```