gcanti / fp-ts-rxjs

fp-ts bindings for RxJS
https://gcanti.github.io/fp-ts-rxjs/
MIT License
187 stars 29 forks source link

`ObservableEither` retry operator #32

Open OliverJAsh opened 3 years ago

OliverJAsh commented 3 years ago

RxJS has a really useful operator called retry. However, this works on the assumption that you only want to retry when the observable throws an error.

When we're using Eithers inside of an Observable, our observable won't throw an error but rather it will emit an Either Left. Thus, we want to "retry" the observable when it emits an Either Left.

Perhaps we could add an operator to ObservableEither for this purpose. Something like:

export const retryForEither = <E, A>(
  number: number,
): RxJS.OperatorFunction<Either.Either<E, A>, Either.Either<E, A>> => t$ =>
  t$.pipe(
    RxJSOperators.mergeMap(t => (Either.isLeft(t) ? RxJS.throwError(t) : RxJS.of(t))),
    RxJSOperators.retry(number),
    RxJSOperators.catchError(e =>
      Either.isLeft(e) ? RxJS.of(e as Either.Either<E, never>) : RxJS.throwError(e),
    ),
  );
waynevanson commented 3 years ago

Make a PR, very useful :)

// ObservableEither.ts
export const retry = <E, A>(
   number: number,
 ): RxJS.OperatorFunction<Either.Either<E, A>, Either.Either<E, A>> => t$ =>
   t$.pipe(
     RxJSOperators.mergeMap(t => (Either.isLeft(t) ? RxJS.throwError(t) : RxJS.of(t))),
     RxJSOperators.retry(number),
     RxJSOperators.catchError(e =>
-      Either.isLeft(e) ? RxJS.of(e as Either.Either<E, never>) : RxJS.throwError(e),
+      Either.isLeft(e) ? RxJS.of(e as Either.Either<E, A>) : RxJS.throwError(e),
     ),
   );
anthonyjoeseph commented 3 years ago

retryWhen would also be cool

anilanar commented 2 years ago

There's another important difference between fp-ts errors and rxjs errors: fp-ts errors do not stop the observable, but rxjs errors do.

So with the proposed retry operator, there would be the following difference, just to make a note of it.

A-B-C-D-E-F

// chain to
A'-B'-C'-error-E'-F'

// retry with rxjs
A'-B'-C'-replacement

// retry with fp-ts
A'-B'-C'-replacement-E'-F'