diff --git a/src/app/services/base.service.ts b/src/app/services/base.service.ts index 937eb58..d65f950 100644 --- a/src/app/services/base.service.ts +++ b/src/app/services/base.service.ts @@ -1,14 +1,38 @@ import {Injectable} from '@angular/core'; -import {HttpHeaders} from '@angular/common/http'; +import { HttpErrorResponse, HttpHeaders} from '@angular/common/http'; +import {delay, mergeMap, retryWhen} from 'rxjs/operators'; +import {Observable, of, throwError} from 'rxjs'; + +const httpTooManyCode = 429; +const httpHeaderRateRetry = 'Retry-After'; @Injectable({ providedIn: 'root' }) export abstract class BaseService { protected headers: HttpHeaders; - protected constructor() { this.headers = new HttpHeaders(); this.headers.set('Content-Type', 'application/json'); } + + /** + * Retries a request according to the rate limit + * @param maxRetry + */ + protected retryRated(maxRetry = 3) { + let retries = maxRetry; + return (src: Observable) => { + return src.pipe(retryWhen(errors => errors.pipe(mergeMap(error => { + if (error.status === httpTooManyCode) { + const retryAfter = Number(error.headers.get(httpHeaderRateRetry) || 1) * 1000; + return of(error.status).pipe(delay(retryAfter)); + } else if (retries-- > 0) { + return of(error).pipe(delay(10000)); + } + return throwError(error); + })) + )); + }; + } } diff --git a/src/app/services/feed/feed.service.ts b/src/app/services/feed/feed.service.ts index 9e18e45..0b86821 100644 --- a/src/app/services/feed/feed.service.ts +++ b/src/app/services/feed/feed.service.ts @@ -1,5 +1,5 @@ import {Injectable} from '@angular/core'; -import {HttpClient} from '@angular/common/http'; +import {HttpClient, HttpErrorResponse} from '@angular/common/http'; import {Post} from 'src/app/models/post'; import {Author} from 'src/app/models/author'; import {environment} from 'src/environments/environment'; @@ -180,7 +180,7 @@ export class FeedService extends BaseService { } }; - return this.http.post(environment.graphQLUrl, body, {headers: this.headers}); + return this.http.post(environment.graphQLUrl, body, {headers: this.headers}).pipe(this.retryRated()); } /** @@ -194,7 +194,7 @@ export class FeedService extends BaseService { } }; - return this.http.post(environment.graphQLUrl, body, {headers: this.headers}); + return this.http.post(environment.graphQLUrl, body, {headers: this.headers}).pipe(this.retryRated()); } /** @@ -209,8 +209,8 @@ export class FeedService extends BaseService { postId: pPostID } }; - - return this.http.post(environment.graphQLUrl, body, {headers: this.headers}); + return this.http.post(environment.graphQLUrl, body, {headers: this.headers}) + .pipe(this.retryRated()); } /** @@ -222,7 +222,9 @@ export class FeedService extends BaseService { this.postsAvailable.next(true); this.posts.next([]); return this.http.post(environment.graphQLUrl, FeedService.buildGetPostBody(sort, 0), - {headers: this.headers}).subscribe(response => { + {headers: this.headers}) + .pipe(this.retryRated()) + .subscribe(response => { this.posts.next(this.constructAllPosts(response)); this.activePostList = sort; }); @@ -235,6 +237,7 @@ export class FeedService extends BaseService { this.offset += this.offsetStep; const body = FeedService.buildGetPostBody(this.activePostList, this.offset); this.http.post(environment.graphQLUrl, body, {headers: this.headers}) + .pipe(this.retryRated()) .subscribe(response => { const posts = this.constructAllPosts(response); const updatedPostList = this.posts.getValue().concat(posts);