Implement healthcheck service
FarmMaps.Develop/FarmMapsLib/pipeline/head This commit looks good Details

2022.01
Willem Dantuma 2020-07-22 20:31:12 +02:00
parent e525227865
commit d494a7c7d6
5 changed files with 103 additions and 74 deletions

View File

@ -10,6 +10,7 @@ import { IEventMessage } from '../../models/event.message';
import { IListItem} from '../../models/list.item';
import { EventService } from '../../services/event.service';
import * as commonActions from '../../actions/app-common.actions';
import { HealthCheckService } from '../../services/healthcheck.service';
import * as appReducers from '../../reducers/app-common.reducer';
@ -46,26 +47,18 @@ export class AppComponent implements OnInit, OnDestroy {
private meta: Meta,
private store: Store<appReducers.State>,
private eventService: EventService,
private healthCheckService: HealthCheckService
) {
var connection = navigator['connection'] || navigator['mozConnection'] || navigator['webkitConnection'];
if(connection) {
this.setOnOffline(connection);
connection.addEventListener('change', () => {
this.setOnOffline(connection);
});
}
}
setOnOffline(connection:any) {
console.debug(connection);
if(connection.downlink == 0) {
this.store.dispatch(new commonActions.Offline());
} else {
//check health every 30 seconds
this.healthCheckService.check(30000).subscribe((online) => {
if(online) {
this.store.dispatch(new commonActions.Online());
}
} else {
this.store.dispatch(new commonActions.Offline());
}
});
}
getActionFromEvent(event: IEventMessage): Action {

View File

@ -165,18 +165,21 @@ export class AppCommonEffects {
@Effect({ dispatch: false })
online$: Observable<Action> = this.actions$.pipe(
ofType(appCommonActions.ONLINE),
map((action) => {
console.debug("Online: Check token");
if(!this.oauthService$.hasValidAccessToken()) {
console.debug("No valid token, try to refresh");
if(this.oauthService$.getRefreshToken() != null ) {
console.debug("We have a refresh token");
this.oauthService$.refreshToken().then(() => {
this.store$.dispatch(new appCommonActions.InitUser());
});
}
withLatestFrom(this.store$.select(appCommonReducers.SelectGetIsOnline)),
switchMap(([action,isOnline]) => {
if(!isOnline) {
console.debug("Online: Check token");
if(!this.oauthService$.hasValidAccessToken()) {
console.debug("No valid token, try to refresh");
if(this.oauthService$.getRefreshToken() != null ) {
console.debug("We have a refresh token");
this.oauthService$.refreshToken().then(() => {
this.store$.dispatch(new appCommonActions.InitUser());
});
}
}
}
return null;
return of(undefined);
}));

View File

@ -0,0 +1,30 @@
import { Injectable } from '@angular/core';
import { Observable,BehaviorSubject,of } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { HttpClient, HttpXhrBackend } from "@angular/common/http";
import { AppConfig } from "../shared/app.config";
@Injectable({
providedIn: 'root',
})
export class HealthCheckService {
private httpClient: HttpClient;
constructor(xhrBackend: HttpXhrBackend, public appConfig: AppConfig) {
this.httpClient = new HttpClient(xhrBackend);
}
ApiEndpoint() {
return this.appConfig.getConfig("apiEndPoint");
}
check(interval:number): Observable<boolean> {
let retval = new BehaviorSubject<boolean>(false);
setInterval(() => {
this.httpClient.get(`${this.ApiEndpoint()}/api/v1/healthcheck`).pipe(map(() => true),catchError((error) => of(false))).toPromise().then((status) => {
retval.next(status);
});
},interval);
return retval;
}
}

View File

@ -1,47 +1,45 @@
import { Injectable, Injector, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common'
import { AppConfig } from "./app.config";
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor
} from '@angular/common/http';
import { OAuthService } from 'angular-oauth2-oidc';
import { Observable } from 'rxjs';
@Injectable()
export class AccessTokenInterceptor implements HttpInterceptor {
private oauthService: OAuthService = null;
private audience: string[] = [];
private base: string;
constructor(private injector: Injector, private appConfig: AppConfig, @Inject(DOCUMENT) private document: any) {
this.base = document.location.href;
}
hasAudience(url: string): boolean {
let u = new URL(url,this.base);
for (let audience of this.audience) {
if (u.href.startsWith(audience)) return true;
}
return false;
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (this.oauthService && this.hasAudience(request.url)) {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${this.oauthService.getAccessToken()}`
}
// Please uncomment the next line if you need to connect to the backend running in Docker.
//, url: `http://localhost:8082${request.url}`
});
} else {
this.oauthService = this.injector.get(OAuthService, null);
if(this.oauthService && this.oauthService.issuer) this.audience = (this.appConfig.getConfig("audience") as string).split(",");
}
return next.handle(request);
}
}
import { Injectable, Injector, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common'
import { AppConfig } from "./app.config";
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor
} from '@angular/common/http';
import { OAuthService } from 'angular-oauth2-oidc';
import { Observable } from 'rxjs';
@Injectable()
export class AccessTokenInterceptor implements HttpInterceptor {
private oauthService: OAuthService = null;
private audience: string[] = [];
private base: string;
constructor(private injector: Injector, private appConfig: AppConfig, @Inject(DOCUMENT) private document: any) {
this.base = document.location.href;
}
hasAudience(url: string): boolean {
let u = new URL(url,this.base);
for (let audience of this.audience) {
if (u.href.startsWith(audience)) return true;
}
return false;
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (this.oauthService && this.hasAudience(request.url)) {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${this.oauthService.getAccessToken()}`
}
});
} else {
this.oauthService = this.injector.get(OAuthService, null);
if(this.oauthService && this.oauthService.issuer) this.audience = (this.appConfig.getConfig("audience") as string).split(",");
}
return next.handle(request);
}
}

View File

@ -6,4 +6,9 @@ import { Component } from '@angular/core';
})
export class AppRootComponent {
title = 'FarmMaps';
constructor() {
window.addEventListener('online', () => console.log('came online'));
window.addEventListener('offline', () => console.log('came offline'));
}
}