Skip to content

Commit

Permalink
Merge pull request #2498 from cloudfoundry-incubator/skip-failed-endp…
Browse files Browse the repository at this point in the history
…oint

Ensure requests to multiple endpoints continue if one fails
  • Loading branch information
nwmac authored Jun 22, 2018
2 parents ab5a394 + 70d2495 commit fb11e43
Showing 1 changed file with 20 additions and 17 deletions.
37 changes: 20 additions & 17 deletions src/frontend/app/store/effects/api.effects.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@

import { of as observableOf, Observable, forkJoin } from 'rxjs';

import { catchError, withLatestFrom, map, mergeMap } from 'rxjs/operators';

import { Injectable } from '@angular/core';
import { Headers, Http, Request, URLSearchParams } from '@angular/http';
import { Actions, Effect } from '@ngrx/effects';
import { Store } from '@ngrx/store';
import { normalize, Schema } from 'normalizr';
import { forkJoin, Observable, of as observableOf } from 'rxjs';
import { catchError, map, mergeMap, withLatestFrom } from 'rxjs/operators';

import { LoggerService } from '../../core/logger.service';
import { SendEventAction } from '../actions/internal-events.actions';
Expand Down Expand Up @@ -127,22 +124,28 @@ export class APIEffect {
if (requestType === 'fetch' && (errors && errors.length > 0)) {
this.handleApiEvents(errors);
}

let fakedAction, errorMessage;
errors.forEach(error => {
if (error.error) {
const fakedAction = { ...actionClone, endpointGuid: error.guid };
const errorMessage = error.errorResponse ? error.errorResponse.description || error.errorCode : error.errorCode;
// Dispatch a error action for the specific endpoint that's failed
fakedAction = { ...actionClone, endpointGuid: error.guid };
errorMessage = error.errorResponse ? error.errorResponse.description || error.errorCode : error.errorCode;
this.store.dispatch(new APISuccessOrFailedAction(fakedAction.actions[2], fakedAction, errorMessage));
this.store.dispatch(new WrapperRequestActionFailed(
errorMessage,
{ ...actionClone, endpointGuid: error.guid },
requestType
));
}
});
const hasError = errors.findIndex(error => error.error) >= 0;
if (hasError) {

// If this request only went out to a single endpoint ... and it failed... send the failed action now and avoid response validation.
// This allows requests sent to multiple endpoints to proceed even if one of those endpoints failed.
if (errors.length === 1 && errors[0].error) {
this.store.dispatch(new WrapperRequestActionFailed(
errorMessage,
{ ...actionClone, endpointGuid: errors[0].guid },
requestType
));
return [];
}

return [new ValidateEntitiesStart(
actionClone,
entities.result,
Expand Down Expand Up @@ -265,15 +268,15 @@ export class APIEffect {
});
}

getEntities(apiAction: IRequestAction, data): {
getEntities(apiAction: IRequestAction, data, errors: APIErrorCheck[]): {
entities: NormalizedResponse
totalResults: number,
totalPages: number,
} {
let totalResults = 0;
let totalPages = 0;
const allEntities = Object.keys(data)
.filter(guid => data[guid] !== null)
.filter(guid => data[guid] !== null && !errors.findIndex(error => error.guid === guid))
.map(cfGuid => {
const cfData = data[cfGuid];
switch (apiAction.entityLocation) {
Expand Down Expand Up @@ -379,7 +382,7 @@ export class APIEffect {
let totalPages = 0;

if (resData) {
const entityData = this.getEntities(apiAction, resData);
const entityData = this.getEntities(apiAction, resData, errors);
entities = entityData.entities;
totalResults = entityData.totalResults;
totalPages = entityData.totalPages;
Expand Down

0 comments on commit fb11e43

Please sign in to comment.