show health even when not completed and reword restart-shutdown

This commit is contained in:
Matt Hill
2021-10-21 22:48:15 -06:00
committed by Aiden McClelland
parent c30141c4f0
commit 502fdeea78
7 changed files with 89 additions and 17 deletions

View File

@@ -307,7 +307,7 @@ export class AppComponent {
this.updateToast = await this.toastCtrl.create({ this.updateToast = await this.toastCtrl.create({
header: 'EOS download complete!', header: 'EOS download complete!',
message: `Restart Embassy for changes to take effect.`, message: 'Restart your Embassy for these updates to take effect. It can take several minutes to come back online.',
position: 'bottom', position: 'bottom',
duration: 0, duration: 0,
cssClass: 'success-toast', cssClass: 'success-toast',

View File

@@ -52,7 +52,7 @@
<!-- ** !restoring/backing-up ** --> <!-- ** !restoring/backing-up ** -->
<ng-container *ngIf="!([PS.BackingUp, PS.Restoring] | includes : statuses.primary)"> <ng-container *ngIf="!([PS.BackingUp, PS.Restoring] | includes : statuses.primary)">
<!-- ** health checks ** --> <!-- ** health checks ** -->
<ng-container *ngIf="!(healthChecks | empty)"> <ng-container *ngIf="statuses.primary === PS.Running && !(healthChecks | empty)">
<ion-item-divider>Health Checks</ion-item-divider> <ion-item-divider>Health Checks</ion-item-divider>
<ng-container *ngIf="connectionFailure"> <ng-container *ngIf="connectionFailure">
<ion-item *ngFor="let health of healthChecks | keyvalue"> <ion-item *ngFor="let health of healthChecks | keyvalue">
@@ -67,7 +67,7 @@
</ng-container> </ng-container>
<ng-container *ngIf="!connectionFailure"> <ng-container *ngIf="!connectionFailure">
<ion-item *ngFor="let health of healthChecks | keyvalue : asIsOrder"> <ion-item *ngFor="let health of healthChecks | keyvalue : asIsOrder">
<ng-container *ngIf="$any(health.value).result as result"> <ng-container *ngIf="health.value?.result as result; else noResult">
<ion-spinner class="icon-spinner" color="primary" slot="start" *ngIf="[HealthResult.Starting, HealthResult.Loading] | includes : result"></ion-spinner> <ion-spinner class="icon-spinner" color="primary" slot="start" *ngIf="[HealthResult.Starting, HealthResult.Loading] | includes : result"></ion-spinner>
<ion-icon slot="start" *ngIf="result === HealthResult.Success" name="checkmark" color="success"></ion-icon> <ion-icon slot="start" *ngIf="result === HealthResult.Success" name="checkmark" color="success"></ion-icon>
<ion-icon slot="start" *ngIf="result === HealthResult.Failure" name="warning-outline" color="warning"></ion-icon> <ion-icon slot="start" *ngIf="result === HealthResult.Failure" name="warning-outline" color="warning"></ion-icon>
@@ -79,6 +79,13 @@
<p *ngIf="result === HealthResult.Failure"><ion-text color="warning">{{ $any(health.value).error }}</ion-text></p> <p *ngIf="result === HealthResult.Failure"><ion-text color="warning">{{ $any(health.value).error }}</ion-text></p>
</ion-label> </ion-label>
</ng-container> </ng-container>
<ng-template #noResult>
<ion-spinner class="icon-spinner" color="dark" slot="start"></ion-spinner>
<ion-label>
<h2 style="font-weight: bold;">{{ health.key }}</h2>
<p>Awaiting result...</p>
</ion-label>
</ng-template>
</ion-item> </ion-item>
</ng-container> </ng-container>
</ng-container> </ng-container>

View File

@@ -42,7 +42,7 @@ export class AppShowPage {
} = { } as any } = { } as any
connectionFailure: boolean connectionFailure: boolean
loading = true loading = true
healthChecks: { [id: string]: HealthCheckResult } = { } healthChecks: { [id: string]: HealthCheckResult | null }
installProgress: ProgressData installProgress: ProgressData
@ViewChild(IonContent) content: IonContent @ViewChild(IonContent) content: IonContent
@@ -66,6 +66,11 @@ export class AppShowPage {
async ngOnInit () { async ngOnInit () {
this.pkgId = this.route.snapshot.paramMap.get('pkgId') this.pkgId = this.route.snapshot.paramMap.get('pkgId')
this.pkg = this.patch.data['package-data'][this.pkgId] this.pkg = this.patch.data['package-data'][this.pkgId]
this.statuses = renderPkgStatus(this.pkg)
this.healthChecks = Object.keys(this.pkg.manifest['health-checks']).reduce((obj, key) => {
obj[key] = null
return obj
}, { })
this.subs = [ this.subs = [
// 1 // 1
@@ -105,9 +110,13 @@ export class AppShowPage {
) )
.subscribe(main => { .subscribe(main => {
if (main.status === PackageMainStatus.Running) { if (main.status === PackageMainStatus.Running) {
this.healthChecks = { ...main.health } Object.keys(this.healthChecks).forEach(key => {
this.healthChecks[key] = main.health[key]
})
} else { } else {
this.healthChecks = { } Object.keys(this.healthChecks).forEach(key => {
this.healthChecks[key] = null
})
} }
}), }),

View File

@@ -65,7 +65,7 @@
</h2> </h2>
<h2 class="notification-message"> <h2 class="notification-message">
{{ not.message }} {{ not.message }}
<a *ngIf="not.code === 1" style="text-decoration: none;" (click)="viewBackupReport(not)"> <a *ngIf="not.code === 1" style="text-decoration: none; cursor: pointer;" (click)="viewBackupReport(not)">
View Report View Report
</a> </a>
</h2> </h2>

View File

@@ -1,7 +1,7 @@
import { Component } from '@angular/core' import { Component } from '@angular/core'
import { ApiService } from 'src/app/services/api/embassy-api.service' import { ApiService } from 'src/app/services/api/embassy-api.service'
import { ServerNotification, ServerNotifications } from 'src/app/services/api/api.types' import { ServerNotification, ServerNotifications } from 'src/app/services/api/api.types'
import { AlertController, LoadingController } from '@ionic/angular' import { AlertController, LoadingController, AlertButton } from '@ionic/angular'
import { ActivatedRoute } from '@angular/router' import { ActivatedRoute } from '@angular/router'
import { ErrorToastService } from 'src/app/services/error-toast.service' import { ErrorToastService } from 'src/app/services/error-toast.service'
@@ -93,7 +93,7 @@ export class NotificationsPage {
const data = notification.data const data = notification.data
const embassyFailed = !!data.server.error const embassyFailed = !!data.server.error
const packagesFailed = Object.entries(data.packages).some(([_, val]) => val.error) const packagesFailed = Object.values(data.packages).some(val => val.error)
let message: string let message: string
@@ -103,7 +103,7 @@ export class NotificationsPage {
message = 'All items were successfully backed up' message = 'All items were successfully backed up'
} }
const buttons: any[] = [ // why can't I import AlertButton? const buttons: AlertButton[] = [
{ {
text: 'Dismiss', text: 'Dismiss',
role: 'cancel', role: 'cancel',

View File

@@ -30,7 +30,7 @@ export class ServerShowPage {
async presentAlertRestart () { async presentAlertRestart () {
const alert = await this.alertCtrl.create({ const alert = await this.alertCtrl.create({
header: 'Confirm', header: 'Confirm',
message: `Are you sure you want to restart your Embassy?`, message: 'Are you sure you want to restart your Embassy? It can take several minutes to come back online.',
buttons: [ buttons: [
{ {
text: 'Cancel', text: 'Cancel',
@@ -51,7 +51,7 @@ export class ServerShowPage {
async presentAlertShutdown () { async presentAlertShutdown () {
const alert = await this.alertCtrl.create({ const alert = await this.alertCtrl.create({
header: 'Warning', header: 'Warning',
message: `Embassy will remain off. To power back on, you will need to unplug the device and plug it back in.`, message: 'Are you sure you want to power down your Embassy? This can take several minutes, and your Embassy will not come back online automatically. To power on again, You will need to physically unplug your Embassy and plug it back in.',
buttons: [ buttons: [
{ {
text: 'Cancel', text: 'Cancel',

View File

@@ -445,7 +445,7 @@ export class MockApiService extends ApiService {
async startPackageRaw (params: RR.StartPackageReq): Promise<RR.StartPackageRes> { async startPackageRaw (params: RR.StartPackageReq): Promise<RR.StartPackageRes> {
await pauseFor(2000) await pauseFor(2000)
const path = `/package-data/${params.id}/installed/status/main` const path = `/package-data/${params.id}/installed/status/main`
const patch = [ const patch1 = [
{ {
op: PatchOp.REPLACE, op: PatchOp.REPLACE,
path: path + '/status', path: path + '/status',
@@ -457,7 +457,58 @@ export class MockApiService extends ApiService {
value: new Date().toISOString(), value: new Date().toISOString(),
}, },
] ]
return this.http.rpcRequest<WithRevision<null>>({ method: 'db.patch', params: { patch } }) const res = await this.http.rpcRequest<WithRevision<null>>({ method: 'db.patch', params: { patch: patch1 } })
setTimeout(async () => {
const patch2 = [
{
op: PatchOp.REPLACE,
path: path + '/health',
value: {
'ephemeral-health-check': {
result: 'starting',
},
'unnecessary-health-check': {
result: 'disabled',
},
},
},
]
await this.http.rpcRequest<WithRevision<null>>({ method: 'db.patch', params: { patch: patch2 } })
await pauseFor(2000)
const patch3 = [
{
op: PatchOp.REPLACE,
path: path + '/health',
value: {
'ephemeral-health-check': {
result: 'starting',
},
'unnecessary-health-check': {
result: 'disabled',
},
'chain-state': {
result: 'loading',
message: 'Bitcoin is syncing from genesis',
},
'p2p-interface': {
result: 'success',
},
'rpc-interface': {
result: 'failure',
error: 'RPC interface unreachable.',
},
},
},
]
await this.http.rpcRequest<WithRevision<null>>({ method: 'db.patch', params: { patch: patch3 } })
}, 4000)
return res
} }
async dryStopPackage (params: RR.DryStopPackageReq): Promise<RR.DryStopPackageRes> { async dryStopPackage (params: RR.DryStopPackageReq): Promise<RR.DryStopPackageRes> {
@@ -474,20 +525,25 @@ export class MockApiService extends ApiService {
async stopPackageRaw (params: RR.StopPackageReq): Promise<RR.StopPackageRes> { async stopPackageRaw (params: RR.StopPackageReq): Promise<RR.StopPackageRes> {
await pauseFor(2000) await pauseFor(2000)
const path = `/package-data/${params.id}/installed/status/main/status` const path = `/package-data/${params.id}/installed/status/main`
const patch = [ const patch = [
{ {
op: PatchOp.REPLACE, op: PatchOp.REPLACE,
path, path: path + '/status',
value: PackageMainStatus.Stopping, value: PackageMainStatus.Stopping,
}, },
{
op: PatchOp.REPLACE,
path: path + '/health',
value: { },
},
] ]
const res = await this.http.rpcRequest<WithRevision<null>>({ method: 'db.patch', params: { patch } }) const res = await this.http.rpcRequest<WithRevision<null>>({ method: 'db.patch', params: { patch } })
setTimeout(() => { setTimeout(() => {
const patch = [ const patch = [
{ {
op: PatchOp.REPLACE, op: PatchOp.REPLACE,
path, path: path + '/status',
value: PackageMainStatus.Stopped, value: PackageMainStatus.Stopped,
}, },
] ]