Skip to content

Commit

Permalink
Merge pull request #3133 from cloudfoundry-incubator/fix-stale-cell-o…
Browse files Browse the repository at this point in the history
…n-instance-scale

Update app instance cell data when scaling up
  • Loading branch information
nwmac authored Dec 3, 2018
2 parents 0937ae9 + 7e6be37 commit b371dae
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 16 deletions.
13 changes: 13 additions & 0 deletions src/frontend/app/features/endpoints/endpoint-helpers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { first, map } from 'rxjs/operators';
import { Validators } from '@angular/forms';

import { urlValidationExpression } from '../../core/utils.service';
import { AppState } from '../../store/app-state';
import { endpointSchemaKey } from '../../store/helpers/entity-factory';
import { selectEntities } from '../../store/selectors/api.selectors';
import { EndpointModel, EndpointType } from './../../store/types/endpoint.types';

export function getFullEndpointApiUrl(endpoint: EndpointModel) {
Expand Down Expand Up @@ -109,6 +115,13 @@ export function getIconForEndpoint(type: string): EndpointIcon {
return icon;
}

export function endpointHasMetrics(endpointGuid: string, store: Store<AppState>): Observable<boolean> {
return store.select(selectEntities<EndpointModel>(endpointSchemaKey)).pipe(
first(),
map(state => !!state[endpointGuid].metadata && !!state[endpointGuid].metadata.metrics)
);
}

export function getEndpointAuthTypes() {
return endpointAuthTypes;
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ import { CfAppInstancesDataSource } from './cf-app-instances-data-source';
import { TableCellCfCellComponent } from './table-cell-cf-cell/table-cell-cf-cell.component';
import { TableCellUsageComponent } from './table-cell-usage/table-cell-usage.component';

export function createAppInstancesMetricAction(appGuid: string, cfGuid: string): FetchApplicationMetricsAction {
return new FetchApplicationMetricsAction(
appGuid,
cfGuid,
new MetricQueryConfig('firehose_container_metric_cpu_percentage'),
MetricQueryType.QUERY
);
}

@Injectable()
export class CfAppInstancesConfigService implements IListConfig<ListAppInstance> {
Expand Down Expand Up @@ -215,12 +223,7 @@ export class CfAppInstancesConfigService implements IListConfig<ListAppInstance>
getInitialised = () => this.initialised$;

private createMetricsResults(entityServiceFactory: EntityServiceFactory) {
const metricsAction = new FetchApplicationMetricsAction(
this.appService.appGuid,
this.appService.cfGuid,
new MetricQueryConfig('firehose_container_metric_cpu_percentage'),
MetricQueryType.QUERY
);
const metricsAction = createAppInstancesMetricAction(this.appService.appGuid, this.appService.cfGuid);
return entityServiceFactory.create<IMetrics<IMetricMatrixResult<IMetricApplication>>>(
metricSchemaKey,
entityFactory(metricSchemaKey),
Expand All @@ -229,5 +232,4 @@ export class CfAppInstancesConfigService implements IListConfig<ListAppInstance>
false
);
}

}
30 changes: 26 additions & 4 deletions src/frontend/app/store/effects/app.effects.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { Injectable } from '@angular/core';
import { Actions, Effect } from '@ngrx/effects';
import { Store } from '@ngrx/store';
import { map } from 'rxjs/operators';
import { first, map } from 'rxjs/operators';

import { endpointHasMetrics } from '../../features/endpoints/endpoint-helpers';
import {
createAppInstancesMetricAction,
} from '../../shared/components/list/list-types/app-instance/cf-app-instances-config.service';
import { GetAppSummaryAction } from '../actions/app-metadata.actions';
import { ASSIGN_ROUTE, AssociateRouteWithAppApplication, ASSIGN_ROUTE_SUCCESS } from '../actions/application-service-routes.actions';
import { ASSIGN_ROUTE_SUCCESS } from '../actions/application-service-routes.actions';
import { UPDATE_SUCCESS, UpdateExistingApplication } from '../actions/application.actions';
import { AppState } from '../app-state';
import { APISuccessOrFailedAction } from '../types/request.types';

Expand All @@ -17,10 +22,27 @@ export class AppEffects {
private store: Store<AppState>,
) { }

@Effect({ dispatch: false }) upateSummary$ = this.actions$.ofType<APISuccessOrFailedAction>(ASSIGN_ROUTE_SUCCESS).pipe(
@Effect({ dispatch: false }) updateSummary$ = this.actions$.ofType<APISuccessOrFailedAction>(ASSIGN_ROUTE_SUCCESS).pipe(
map(action => {
this.store.dispatch(new GetAppSummaryAction(action.apiAction.guid, action.apiAction.endpointGuid));
this.store.dispatch(new GetAppSummaryAction(action.apiAction.guid, action.apiAction.endpointGuid));
}),
);

@Effect({ dispatch: false }) clearCellMetrics$ = this.actions$.ofType<APISuccessOrFailedAction>(UPDATE_SUCCESS).pipe(
map(action => {
// User's can scale down instances and previous instance data is kept in store, when the user scales up again this stale data can
// be incorrectly shown straight away. In order to work around this fetch the latest metrics again when scaling up
// Note - If this happens within the metrics update time period (60 seconds) the stale one is returned again, unfortunately there's
// no way to work around this.
const updateAction: UpdateExistingApplication = action.apiAction as UpdateExistingApplication;
if (updateAction.newApplication.instances > updateAction.existingApplication.instances) {
// First check that we have a metrics endpoint associated with this cf
endpointHasMetrics(updateAction.endpointGuid, this.store).pipe(first()).subscribe(hasMetrics => {
if (hasMetrics) {
this.store.dispatch(createAppInstancesMetricAction(updateAction.guid, updateAction.endpointGuid));
}
});
}
}),
);
}
9 changes: 4 additions & 5 deletions src/frontend/app/store/reducers/routes.reducer.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { AppState, IRequestEntityTypeState } from '../app-state';
import { Action } from '@ngrx/store';
import { IAppSummary, IRoute } from '../../core/cf-api.types';
import { ASSIGN_ROUTE_SUCCESS, AssociateRouteWithAppApplication } from '../actions/application-service-routes.actions';
import { DeleteRoute, RouteEvents, UnmapRoute } from '../actions/route.actions';
import { IRequestEntityTypeState } from '../app-state';
import { APIResource } from '../types/api.types';
import { RouteEvents, UnmapRoute, DeleteRoute } from '../actions/route.actions';
import { APISuccessOrFailedAction } from '../types/request.types';
import { IRoute, IAppSummary } from '../../core/cf-api.types';
import { ASSIGN_ROUTE_SUCCESS, AssociateRouteWithAppApplication } from '../actions/application-service-routes.actions';

export function routeReducer(state: IRequestEntityTypeState<APIResource<IRoute>>, action: APISuccessOrFailedAction) {
switch (action.type) {
Expand Down

0 comments on commit b371dae

Please sign in to comment.