feat: add backend status down indicator (#3889)

This commit is contained in:
Nigel Huang
2020-06-15 10:59:28 -04:00
committed by GitHub
parent 2b01e009c6
commit a50edc7055
12 changed files with 165 additions and 40 deletions

View File

@ -4,7 +4,7 @@ import { ThunkDispatch } from 'redux-thunk';
import { AnyAction } from 'redux';
import { actions as notifActions } from 'redux-notifications';
const { notifSend } = notifActions;
const { notifSend, notifDismiss } = notifActions;
export const STATUS_REQUEST = 'STATUS_REQUEST';
export const STATUS_SUCCESS = 'STATUS_SUCCESS';
@ -16,7 +16,10 @@ export function statusRequest() {
};
}
export function statusSuccess(status: { auth: boolean }) {
export function statusSuccess(status: {
auth: { status: boolean };
api: { status: boolean; statusPage: string };
}) {
return {
type: STATUS_SUCCESS,
payload: { status },
@ -26,7 +29,7 @@ export function statusSuccess(status: { auth: boolean }) {
export function statusFailure(error: Error) {
return {
type: STATUS_FAILURE,
error,
payload: { error },
};
}
@ -42,7 +45,30 @@ export function checkBackendStatus() {
const backend = currentBackend(state.config);
const status = await backend.status();
const authError = status.auth === false;
const backendDownKey = 'ui.toast.onBackendDown';
const previousBackendDownNotifs = state.notifs.filter(n => n.message?.key === backendDownKey);
if (status.api.status === false) {
if (previousBackendDownNotifs.length === 0) {
dispatch(
notifSend({
message: {
details: status.api.statusPage,
key: 'ui.toast.onBackendDown',
},
kind: 'danger',
}),
);
}
return dispatch(statusSuccess(status));
} else if (status.api.status === true && previousBackendDownNotifs.length > 0) {
// If backend is up, clear all the danger messages
previousBackendDownNotifs.forEach(notif => {
dispatch(notifDismiss(notif.id));
});
}
const authError = status.auth.status === false;
if (authError) {
const key = 'ui.toast.onLoggedOut';
const existingNotification = state.notifs.find(n => n.message?.key === key);

View File

@ -181,11 +181,17 @@ export class Backend {
async status() {
const attempts = 3;
let status: { auth: boolean } = { auth: false };
let status: {
auth: { status: boolean };
api: { status: boolean; statusPage: string };
} = {
auth: { status: false },
api: { status: false, statusPage: '' },
};
for (let i = 1; i <= attempts; i++) {
status = await this.implementation!.status();
// return on first success
if (Object.values(status).every(s => s === true)) {
if (Object.values(status).every(s => s.status === true)) {
return status;
} else {
await new Promise(resolve => setTimeout(resolve, i * 1000));

View File

@ -3,11 +3,14 @@ import { AnyAction } from 'redux';
import { STATUS_REQUEST, STATUS_SUCCESS, STATUS_FAILURE } from '../actions/status';
import { Status } from '../types/redux';
export interface EntriesAction extends AnyAction {
payload: { status: { auth: boolean }; error?: Error };
interface StatusAction extends AnyAction {
payload: {
status: { auth: { status: boolean }; api: { status: boolean; statusPage: string } };
error?: Error;
};
}
const status = (state = Map(), action: EntriesAction) => {
const status = (state = Map(), action: StatusAction) => {
switch (action.type) {
case STATUS_REQUEST:
return state.set('isFetching', true);