Skip to content

Commit

Permalink
added pulse check to check BE health (#647)
Browse files Browse the repository at this point in the history
* added health check

* minor change

* addressing comments

* addressing comments

* ng build files
  • Loading branch information
shreyakhajanchi authored Nov 10, 2023
1 parent 41d597a commit e3eb37c
Show file tree
Hide file tree
Showing 12 changed files with 112 additions and 8 deletions.
4 changes: 2 additions & 2 deletions ui/dist/ui/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
<link rel="preconnect" href="https://fonts.gstatic.com">
<style type="text/css">@font-face{font-family:'Roboto';font-style:normal;font-weight:300;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCRc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;}@font-face{font-family:'Roboto';font-style:normal;font-weight:300;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fABc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;}@font-face{font-family:'Roboto';font-style:normal;font-weight:300;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCBc4AMP6lbBP.woff2) format('woff2');unicode-range:U+1F00-1FFF;}@font-face{font-family:'Roboto';font-style:normal;font-weight:300;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fBxc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0370-03FF;}@font-face{font-family:'Roboto';font-style:normal;font-weight:300;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCxc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;}@font-face{font-family:'Roboto';font-style:normal;font-weight:300;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fChc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;}@font-face{font-family:'Roboto';font-style:normal;font-weight:300;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fBBc4AMP6lQ.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}@font-face{font-family:'Roboto';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu72xKKTU1Kvnz.woff2) format('woff2');unicode-range:U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;}@font-face{font-family:'Roboto';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu5mxKKTU1Kvnz.woff2) format('woff2');unicode-range:U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;}@font-face{font-family:'Roboto';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7mxKKTU1Kvnz.woff2) format('woff2');unicode-range:U+1F00-1FFF;}@font-face{font-family:'Roboto';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4WxKKTU1Kvnz.woff2) format('woff2');unicode-range:U+0370-03FF;}@font-face{font-family:'Roboto';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7WxKKTU1Kvnz.woff2) format('woff2');unicode-range:U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;}@font-face{font-family:'Roboto';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7GxKKTU1Kvnz.woff2) format('woff2');unicode-range:U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;}@font-face{font-family:'Roboto';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4mxKKTU1Kg.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}@font-face{font-family:'Roboto';font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fCRc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;}@font-face{font-family:'Roboto';font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fABc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;}@font-face{font-family:'Roboto';font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fCBc4AMP6lbBP.woff2) format('woff2');unicode-range:U+1F00-1FFF;}@font-face{font-family:'Roboto';font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fBxc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0370-03FF;}@font-face{font-family:'Roboto';font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fCxc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;}@font-face{font-family:'Roboto';font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fChc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;}@font-face{font-family:'Roboto';font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fBBc4AMP6lQ.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}</style>
<style type="text/css">@font-face{font-family:'Material Icons';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/s/materialicons/v140/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2) format('woff2');}@font-face{font-family:'Material Icons Outlined';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/s/materialiconsoutlined/v109/gok-H7zzDkdnRel8-DQ6KAXJ69wP1tGnf4ZGhUcel5euIg.woff2) format('woff2');}.material-icons{font-family:'Material Icons';font-weight:normal;font-style:normal;font-size:24px;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;-webkit-font-feature-settings:'liga';-webkit-font-smoothing:antialiased;}.material-icons-outlined{font-family:'Material Icons Outlined';font-weight:normal;font-style:normal;font-size:24px;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;-webkit-font-feature-settings:'liga';-webkit-font-smoothing:antialiased;}</style>
<style>.mat-typography{font:400 14px/20px Roboto,Helvetica Neue,sans-serif;letter-spacing:normal}html,body{height:100%;box-sizing:border-box}body{margin:0;font-family:Roboto,Helvetica Neue,sans-serif}</style><link rel="stylesheet" href="styles.77cd407a0323ef69.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles.77cd407a0323ef69.css"></noscript></head>
<style>.mat-typography{font:400 14px/20px Roboto,Helvetica Neue,sans-serif;letter-spacing:normal}html,body{height:100%;box-sizing:border-box}body{margin:0;font-family:Roboto,Helvetica Neue,sans-serif}</style><link rel="stylesheet" href="styles.6d8ba0a3d523f825.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles.6d8ba0a3d523f825.css"></noscript></head>
<body class="mat-typography">
<app-root></app-root>
<script src="runtime.7cb62255c16cf7ce.js" type="module"></script><script src="polyfills.b6adefa6020709e6.js" type="module"></script><script src="main.5614d3df47e8a559.js" type="module"></script>
<script src="runtime.7cb62255c16cf7ce.js" type="module"></script><script src="polyfills.b6adefa6020709e6.js" type="module"></script><script src="main.df84b5efa11daeaf.js" type="module"></script>

</body></html>
1 change: 0 additions & 1 deletion ui/dist/ui/main.5614d3df47e8a559.js

This file was deleted.

1 change: 1 addition & 0 deletions ui/dist/ui/main.df84b5efa11daeaf.js

Large diffs are not rendered by default.

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion ui/src/app/components/home/home.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Component, OnInit } from '@angular/core'
import { MatDialog } from '@angular/material/dialog';
import { Router } from '@angular/router';
import { MigrationDetails } from 'src/app/app.constants';
import { BackendHealthService } from 'src/app/services/backend-health/backend-health.service';
import { InfodialogComponent } from '../infodialog/infodialog.component';

@Component({
Expand All @@ -11,9 +12,11 @@ import { InfodialogComponent } from '../infodialog/infodialog.component';
})
export class HomeComponent implements OnInit {
constructor(private dialog: MatDialog,
private router: Router) { }
private router: Router,
private healthCheckService: BackendHealthService) { }

ngOnInit(): void {
this.healthCheckService.startHealthCheck();
if (localStorage.getItem(MigrationDetails.IsMigrationInProgress) != null && localStorage.getItem(MigrationDetails.IsMigrationInProgress) as string === 'true') {
this.dialog.open(InfodialogComponent, {
data: { title: 'Redirecting to prepare migration page', message: 'Another migration already in progress', type: 'error' },
Expand Down
3 changes: 1 addition & 2 deletions ui/src/app/components/infodialog/infodialog.component.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
<div class="dialog-container">
<h1 mat-dialog-title>{{ data.title }}</h1>
<div mat-dialog-content>
<p class="dialog-message">
{{ data.message }}
<p class="dialog-message" [innerHtml]="data.message">
</p>
</div>
<div mat-dialog-actions class="dialog-action">
Expand Down
16 changes: 16 additions & 0 deletions ui/src/app/services/backend-health/backend-health.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';

import { BackendHealthService } from './backend-health.service';

describe('BackendHealthService', () => {
let service: BackendHealthService;

beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(BackendHealthService);
});

it('should be created', () => {
expect(service).toBeTruthy();
});
});
75 changes: 75 additions & 0 deletions ui/src/app/services/backend-health/backend-health.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { catchError, from, interval, map, Observable, of, Subject, Subscription, takeUntil } from 'rxjs';
import { InfodialogComponent } from 'src/app/components/infodialog/infodialog.component';
import { FetchService } from '../fetch/fetch.service';

@Injectable({
providedIn: 'root'
})
export class BackendHealthService {
private healthCheckSubscription: Subscription = new Subscription;
private unHealthyCheckCount: number = 0;
private MAX_UNHEALTHY_CHECK_ATTEMPTS: number = 5

constructor(private fetch: FetchService,
private dialog: MatDialog) { }

startHealthCheck() {
this.healthCheckSubscription = interval(5000).subscribe(() => {
this.checkBackendHealth();
});
}

stopHealthCheck() {
if (this.healthCheckSubscription) {
this.healthCheckSubscription.unsubscribe();
}
}

checkBackendHealth() {
this.checkHealth().subscribe(
(isHealthy) => {
if (!isHealthy) {
if (this.unHealthyCheckCount == this.MAX_UNHEALTHY_CHECK_ATTEMPTS) {
// Backend is unhealthy, open the dialog and unsubscribe
this.openHealthDialog();
}
this.unHealthyCheckCount++;
} else {
this.unHealthyCheckCount = 0;
}
}
);
}

openHealthDialog() {
let dialogRef = this.dialog.open(InfodialogComponent, {
width: '500px',
data: {
message: "Please check terminal logs for more details. In case of a crash please file a <a href='https://github.com/GoogleCloudPlatform/spanner-migration-tool/issues' target='_blank' class='a-link'>github</a> issue with all the details.",
type: 'error',
title: 'Spanner migration tool unresponsive',
}
});
this.stopHealthCheck();
dialogRef.afterClosed().subscribe(() => {
this.startHealthCheck();
})
}

checkHealth(): Observable<boolean> {
return from(this.fetch.checkBackendHealth()).pipe(
map(() => true),
catchError(() => {
return of(false);
})
);
}

ngOnDestroy() {
// Stop health checks when the service is destroyed
this.stopHealthCheck();
}
}
3 changes: 3 additions & 0 deletions ui/src/app/services/fetch/fetch.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,4 +303,7 @@ export class FetchService {
getPGSQLToStandardTypeTypemap() {
return this.http.get<Map<string,string>>(`${this.url}/typemap/GetPGSQLToStandardTypeTypemap`)
}
checkBackendHealth() {
return this.http.get(`${this.url}/ping`)
}
}
5 changes: 4 additions & 1 deletion ui/src/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -242,9 +242,12 @@ body {
.dialog-message {
padding-top: 1rem;
padding-bottom: 1rem;
display: flex;
display: block;
justify-content: center;
align-items: center;
.a-link {
outline: none !important;
}
}

.dialog-action {
Expand Down
1 change: 1 addition & 0 deletions webv2/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ func getRoutes() *mux.Router {
router.HandleFunc("/uploadFile", uploadFile).Methods("POST")

router.HandleFunc("/GetTableWithErrors", getTableWithErrors).Methods("GET")
router.HandleFunc("/ping", getBackendHealth).Methods("GET")

router.PathPrefix("/").Handler(frontendStatic)
return router
Expand Down
4 changes: 4 additions & 0 deletions webv2/web.go
Original file line number Diff line number Diff line change
Expand Up @@ -1445,6 +1445,10 @@ type TableInterleaveStatus struct {
Comment string
}

func getBackendHealth(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}

// setParentTable checks whether specified table can be interleaved, and updates the schema to convert foreign
// key to interleaved table if 'update' parameter is set to true. If 'update' parameter is set to false, then return
// whether the foreign key can be converted to interleave table without updating the schema.
Expand Down

0 comments on commit e3eb37c

Please sign in to comment.