From 44d73f3e7e36ebd09e7bddc43412fc70134e9f7d Mon Sep 17 00:00:00 2001 From: ta264 Date: Mon, 18 May 2020 21:36:48 +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 f22975bae..715ea1755 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() { @@ -286,7 +286,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..2bd30e22f --- /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://wiki.servarr.com/Readarr_System#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 8165f3e3b..dd13b0a9c 100644 --- a/frontend/src/System/Status/Health/HealthConnector.js +++ b/frontend/src/System/Status/Health/HealthConnector.js @@ -4,18 +4,19 @@ import { connect } from 'react-redux'; import { createSelector } from 'reselect'; import { testAllDownloadClients, testAllIndexers } from 'Store/Actions/settingsActions'; import { fetchHealth } from 'Store/Actions/systemActions'; +import createHealthCheckSelector from 'Store/Selectors/createHealthCheckSelector'; 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 765baa351..e609dd712 100644 --- a/frontend/src/System/Status/Health/HealthStatusConnector.js +++ b/frontend/src/System/Status/Health/HealthStatusConnector.js @@ -4,17 +4,19 @@ import { connect } from 'react-redux'; import { createSelector } from 'reselect'; import PageSidebarStatus from 'Components/Page/Sidebar/PageSidebarStatus'; import { fetchHealth } from 'Store/Actions/systemActions'; +import createHealthCheckSelector from 'Store/Selectors/createHealthCheckSelector'; 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; }