Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpected behavior for retry with delay operator in angular on interceptor #7192

Open
adrian-badulescu opened this issue Feb 21, 2023 · 2 comments

Comments

@adrian-badulescu
Copy link

Describe the bug

I got a very weird behavior from my retry on error Angular interceptor.
If I am using the simple form of retry operator -- retry(2) the interceptor does what is supposed to do, retry twice, but if I am using the retry object configurator -- RetryConfig retry({ count: 2, delay: 2000, resetOnSuccess: true }) then I got the effect of Infinity mentioned -- here in the documentation retry(configOrCount: number | RetryConfig = Infinity): MonoTypeOperatorFunction

It is worth to be mentioned that if I am using retry with the configuration object outside the Interceptor -- directly over HttpClient class, it works perfectly as for example:

import { Inject, Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { catchError, retry } from 'rxjs/operators';


@Injectable({
  providedIn: 'root'
})
export class WhoisService {
  private _baseUrl: string = '';

  constructor(private http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
    this._baseUrl = baseUrl;
  }

  searchUrl(domainQueried: string): Observable<boolean> {
    return this.http.get<boolean>(`${this._baseUrl}getdomainN/Query?id=${domainQueried}`)
      .pipe(
        retry({ count: 2, delay: 2000, resetOnSuccess: true }),
        catchError(error => of(error))
      )
  }


}

The Interceptor:

import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor,
  HttpErrorResponse
} from '@angular/common/http';
import { catchError, Observable, of, retry, throwError } from 'rxjs';

@Injectable()


export class ErrorInterceptor implements HttpInterceptor {

  constructor() { }

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(request)
    .pipe(
      //retry(2) <-- this works but without delay
      retry({ count: 2, delay: 2000, resetOnSuccess: true }), // <-- Infinity of retries
      catchError(error => of(error)),

    )



  }


}

Maybe someone can explain to me what is happening.

Thank you

Expected behavior

To do retry on http errors, twice with 2 seconds delay

Reproduction code

No response

Reproduction URL

No response

Version

~7.5.5

Environment

{
"name": "newtd",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"prestart": "node aspnetcore-https",
"start": "run-script-os",
"start:windows": "ng serve --port 44417 --ssl --ssl-cert %APPDATA%\ASP.NET\https\%npm_package_name%.pem --ssl-key %APPDATA%\ASP.NET\https\%npm_package_name%.key",
"start:default": "ng serve --port 44417 --ssl --ssl-cert $HOME/.aspnet/https/${npm_package_name}.pem --ssl-key $HOME/.aspnet/https/${npm_package_name}.key",
"build": "ng build",
"build:ssr": "ng run newTD:server:dev",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
"private": true,
"dependencies": {
"@angular/animations": "^14.0.3",
"@angular/common": "^14.0.3",
"@angular/compiler": "^14.0.3",
"@angular/core": "^14.0.3",
"@angular/forms": "^14.0.3",
"@angular/platform-browser": "^14.0.3",
"@angular/platform-browser-dynamic": "^14.0.3",
"@angular/platform-server": "^14.0.3",
"@angular/router": "^14.0.3",
"@faker-js/faker": "^7.6.0",
"bootstrap": "^5.1.3",
"jquery": "^3.6.0",
"oidc-client": "^1.11.5",
"popper.js": "^1.16.0",
"run-script-os": "^1.1.6",
"rxjs": "~7.5.5",
"tslib": "^2.4.0",
"zone.js": "~0.11.6"
},
"devDependencies": {
"@angular-devkit/build-angular": "^14.0.3",
"@angular/cli": "^14.0.3",
"@angular/compiler-cli": "^14.0.3",
"@types/jasmine": "~4.0.3",
"@types/jasminewd2": "~2.0.10",
"@types/node": "^18.0.0",
"jasmine-core": "~4.2.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.1.1",
"karma-coverage": "~2.2.0",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "^2.0.0",
"typescript": "~4.7.4"
},
"overrides": {
"autoprefixer": "10.4.5"
}
}

Additional context

Angular app with .Net Core 6 scaffolded in Visual Studio

@Lougnar
Copy link

Lougnar commented Jun 13, 2023

I encountered same issue with RXJS 7.8.0 and angular 15.2.8. retryCount is always 1 and infinite retry without delay.

Every retried request is reintercepted by interceptor.

I haven't found a workaround yet.

@josepot
Copy link
Contributor

josepot commented Jun 14, 2023

Maybe someone can explain to me what is happening.

Hi @adrian-badulescu and @root14 !

I'm pretty sure that this is what's happening:

next.handle(request) returns an Observable that when it errors, if you synchronously re-subscribe to it , then it synchronously throws the error again.

However, if you re-subscribe to that same Observable after a while (instead of re-subscribing to it synchronously), then the Observable starts emitting events again... until it eventually errors.

What happens is that since you have the resetOnSuccess set to true, then the count starts over every time that the Observable emits a next value (rather than emitting an error). So, there you go: that's what's happening.

It is worth to be mentioned that if I am using retry with the configuration object outside the Interceptor -- directly over HttpClient class, it works perfectly as for example:

I know nothing about Angular, but I'm willing to bet that the Obseravble returned from this.http.get<boolean> doesn't emit intermediate values, thus never having an emission that resets the counter. That's why it works on this.http.get but it doesn't work on the interceptor (which must be emitting intermediate values before error/complete).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants