From e52005fa35f43f3b17c6de2dc9c6850f548878cb Mon Sep 17 00:00:00 2001 From: ta264 Date: Sun, 17 May 2020 09:37:25 +0100 Subject: [PATCH] New: Warn if UI won't update due to SignalR errors --- frontend/src/Components/SignalRConnector.js | 16 +++++++++++-- .../Selectors/createHealthCheckSelector.js | 24 +++++++++++++++++++ .../System/Status/Health/HealthConnector.js | 7 +++--- .../Status/Health/HealthStatusConnector.js | 8 ++++--- 4 files changed, 47 insertions(+), 8 deletions(-) create mode 100644 frontend/src/Store/Selectors/createHealthCheckSelector.js diff --git a/frontend/src/Components/SignalRConnector.js b/frontend/src/Components/SignalRConnector.js index f9e586c98..c2909be73 100644 --- a/frontend/src/Components/SignalRConnector.js +++ b/frontend/src/Components/SignalRConnector.js @@ -120,7 +120,7 @@ class SignalRConnector extends Component { this.connection.on('receiveMessage', this.onReceiveMessage); - this.connection.start().then(this.onConnected); + this.connection.start().then(this.onStart, this.onStartFail); } componentWillUnmount() { @@ -242,7 +242,19 @@ class SignalRConnector extends Component { // // Listeners - onConnected = () => { + onStartFail = (error) => { + console.error('[signalR] failed to connect'); + console.error(error); + + this.props.dispatchSetAppValue({ + isConnected: false, + isReconnecting: false, + isDisconnected: false, + isRestarting: false + }); + } + + onStart = () => { console.debug('[signalR] connected'); this.props.dispatchSetAppValue({ diff --git a/frontend/src/Store/Selectors/createHealthCheckSelector.js b/frontend/src/Store/Selectors/createHealthCheckSelector.js new file mode 100644 index 000000000..1cb74558b --- /dev/null +++ b/frontend/src/Store/Selectors/createHealthCheckSelector.js @@ -0,0 +1,24 @@ +import { createSelector } from 'reselect'; + +function createHealthCheckSelector() { + return createSelector( + (state) => state.system.health, + (state) => state.app, + (health, app) => { + const items = [...health.items]; + + if (!app.isConnected) { + items.push({ + source: 'UI', + type: 'warning', + message: 'Could not connect to SignalR, UI won\'t update', + wikiUrl: 'https://github.com/Radarr/Radarr/wiki/Health-Checks#could-not-connect-to-signalr' + }); + } + + return items; + } + ); +} + +export default createHealthCheckSelector; diff --git a/frontend/src/System/Status/Health/HealthConnector.js b/frontend/src/System/Status/Health/HealthConnector.js index d2adc41cc..082c5ed2c 100644 --- a/frontend/src/System/Status/Health/HealthConnector.js +++ b/frontend/src/System/Status/Health/HealthConnector.js @@ -2,20 +2,21 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; import { connect } from 'react-redux'; import { createSelector } from 'reselect'; +import createHealthCheckSelector from 'Store/Selectors/createHealthCheckSelector'; import { fetchHealth } from 'Store/Actions/systemActions'; import { testAllDownloadClients, testAllIndexers } from 'Store/Actions/settingsActions'; import Health from './Health'; function createMapStateToProps() { return createSelector( + createHealthCheckSelector(), (state) => state.system.health, (state) => state.settings.downloadClients.isTestingAll, (state) => state.settings.indexers.isTestingAll, - (health, isTestingAllDownloadClients, isTestingAllIndexers) => { + (items, health, isTestingAllDownloadClients, isTestingAllIndexers) => { const { isFetching, - isPopulated, - items + isPopulated } = health; return { diff --git a/frontend/src/System/Status/Health/HealthStatusConnector.js b/frontend/src/System/Status/Health/HealthStatusConnector.js index 181eae916..d04db7e62 100644 --- a/frontend/src/System/Status/Health/HealthStatusConnector.js +++ b/frontend/src/System/Status/Health/HealthStatusConnector.js @@ -2,19 +2,21 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; import { connect } from 'react-redux'; import { createSelector } from 'reselect'; +import createHealthCheckSelector from 'Store/Selectors/createHealthCheckSelector'; import { fetchHealth } from 'Store/Actions/systemActions'; import PageSidebarStatus from 'Components/Page/Sidebar/PageSidebarStatus'; function createMapStateToProps() { return createSelector( (state) => state.app, + createHealthCheckSelector(), (state) => state.system.health, - (app, health) => { - const count = health.items.length; + (app, items, health) => { + const count = items.length; let errors = false; let warnings = false; - health.items.forEach((item) => { + items.forEach((item) => { if (item.type === 'error') { errors = true; }