From b45f624ab39288357bdf772ac781fd6eb24973f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20T=C3=B3th?= Date: Thu, 7 Nov 2019 16:08:54 +0100 Subject: [PATCH] Extract status code polling logic into a class --- src/app/dashboard/dashboard.component.html | 2 +- src/app/dashboard/dashboard.component.ts | 47 +++++----------- src/app/dashboard/statuscodepoller.ts | 63 ++++++++++++++++++++++ 3 files changed, 76 insertions(+), 36 deletions(-) create mode 100644 src/app/dashboard/statuscodepoller.ts diff --git a/src/app/dashboard/dashboard.component.html b/src/app/dashboard/dashboard.component.html index f7071f2..06fbf53 100644 --- a/src/app/dashboard/dashboard.component.html +++ b/src/app/dashboard/dashboard.component.html @@ -5,7 +5,7 @@
+ [ngClass]="{'deploy-blur': deploying || (iframeReloadPoller.isPolling | async)}">
diff --git a/src/app/dashboard/dashboard.component.ts b/src/app/dashboard/dashboard.component.ts index a12a8f3..2da4ad9 100644 --- a/src/app/dashboard/dashboard.component.ts +++ b/src/app/dashboard/dashboard.component.ts @@ -1,13 +1,13 @@ import { Component, OnDestroy, OnInit, ChangeDetectorRef, ElementRef, ViewChild } from '@angular/core'; import { DeploymentNotificationService } from '../services/deployment-notification.service'; -import { Subscription, BehaviorSubject } from 'rxjs'; +import { Subscription } from 'rxjs'; import { WebSocketService } from '../services/websocket.service'; import { WebSocketMessage } from '../message-types/websocket-message'; -import { DashboardConfigService } from '../services/config.service'; +import { DashboardConfigService, ConfigReadyService } from '../services/config.service'; import { HttpClient } from '@angular/common/http'; -import { delay, retryWhen, tap } from 'rxjs/operators'; import { FSMUpdateService } from '../services/fsmupdate.service'; import { MessagesComponent } from '../messages/messages.component'; +import { StatusCodePoller } from './statuscodepoller'; @Component({ selector: 'app-dashboard', @@ -16,7 +16,6 @@ import { MessagesComponent } from '../messages/messages.component'; }) export class DashboardComponent implements OnInit, OnDestroy { deploying = false; - polling = new BehaviorSubject(false); deploymentNotificationSubscription: Subscription; @ViewChild('webiframe', {static: false}) webiframe: ElementRef; @ViewChild(MessagesComponent, {static: false}) messages: MessagesComponent; @@ -28,7 +27,7 @@ export class DashboardComponent implements OnInit, OnDestroy { iframeUrl = this.configService.iframeUrl; actualIframeUrl = this.iframeUrl.value; terminalMenuItem = this.configService.terminalMenuItem; - iframeReloadSubscription: Subscription; + iframeReloadPoller: StatusCodePoller; command_handlers = { 'dashboard.reloadFrontend': this.reloadFrontendHandlder.bind(this), @@ -39,6 +38,7 @@ export class DashboardComponent implements OnInit, OnDestroy { private webSocketService: WebSocketService, private changeDetectorRef: ChangeDetectorRef, private http: HttpClient, + private configReadyService: ConfigReadyService, private configService: DashboardConfigService, private fsmUpdateService: FSMUpdateService) {} @@ -46,6 +46,7 @@ export class DashboardComponent implements OnInit, OnDestroy { this.webSocketService.connect(); this.configService.init(); this.subscribeCheckSolution(); + this.iframeReloadPoller = new StatusCodePoller(this.iframeUrl, this.http); this.hideIframeUntilResponseOk(); this.subscribeResizeOnLayoutChange(); this.initCommandHandling(); @@ -63,8 +64,10 @@ export class DashboardComponent implements OnInit, OnDestroy { } hideIframeUntilResponseOk() { - // TODO: hide iframe and show it after this whole deal... - this.reloadIframeWhenResponseOk(); + this.iframeReloadPoller.ok.subscribe(() => this.reloadIframe()); + this.configReadyService.configDone.subscribe(() => + this.iframeReloadPoller.start() + ); } subscribeResizeOnLayoutChange() { @@ -86,7 +89,7 @@ export class DashboardComponent implements OnInit, OnDestroy { (deploying) => { this.deploying = deploying; if (!deploying && this.configService.reloadIframeOnDeploy.value) { - this.reloadIframeWhenResponseOk(); + this.iframeReloadPoller.start(); } }); } @@ -151,36 +154,10 @@ export class DashboardComponent implements OnInit, OnDestroy { this.iframeUrl.next(this.urlbar.nativeElement.value); } - reloadIframeWhenResponseOk() { - if (this.polling.value) { - this.iframeReloadSubscription.unsubscribe(); - } - this.polling.next(true); - this.iframeReloadSubscription = this.http.get(this.actualIframeUrl, {observe: 'response'}).pipe( - retryWhen(errors => - errors.pipe( - tap( - response => { - if (this.iframeUrl.value === '') { - this.iframeReloadSubscription.unsubscribe(); - this.polling.next(false); - } - if (response.status === 200) { - this.iframeReloadSubscription.unsubscribe(); - this.polling.next(false); - this.reloadIframe(); - }}), - delay(1000) - ))).subscribe(); - } - ngOnDestroy() { if (this.deploymentNotificationSubscription) { this.deploymentNotificationSubscription.unsubscribe(); } - - if (this.iframeReloadSubscription) { - this.iframeReloadSubscription.unsubscribe(); - } + this.iframeReloadPoller.stop(); } } diff --git a/src/app/dashboard/statuscodepoller.ts b/src/app/dashboard/statuscodepoller.ts new file mode 100644 index 0000000..299b426 --- /dev/null +++ b/src/app/dashboard/statuscodepoller.ts @@ -0,0 +1,63 @@ +import { HttpClient } from '@angular/common/http'; +import { Subject, Subscription, BehaviorSubject } from 'rxjs'; +import { retryWhen, delay, tap, skip } from 'rxjs/operators'; + +export class StatusCodePoller { + http: HttpClient; + url: BehaviorSubject; + pollFreq: number; + okCode: number; + stopOnOk: boolean; + + pollSubscription: Subscription; + urlSubscription: Subscription; + poll = new Subject(); + ok = new Subject(); + isPolling = new BehaviorSubject(false); + + constructor( + url: BehaviorSubject, http: HttpClient, + pollFreq = 1000, okCode = 200, + stopOnOk = true + ) { + this.url = url; + this.http = http; + this.pollFreq = pollFreq; + this.okCode = okCode; + this.stopOnOk = stopOnOk; + } + + start() { + this.stop(); + if (this.url.value === '') { + return; + } + this.urlSubscription = this.url.pipe(skip(1)).subscribe(() => this.stop()); + this.isPolling.next(true); + this.pollSubscription = this.http.get(this.url.value, {observe: 'response'}).pipe( + retryWhen(errors => + errors.pipe( + tap( + response => { + this.poll.next(response); + if (response.status === this.okCode) { + if (this.stopOnOk) { + this.stop(); + } + this.ok.next(response); + } + }), + delay(this.pollFreq) + ))).subscribe(); + } + + stop() { + this.isPolling.next(false); + if (this.pollSubscription) { + this.pollSubscription.unsubscribe(); + } + if (this.urlSubscription) { + this.urlSubscription.unsubscribe(); + } + } +}