From dc5e73632e02142b22609df57c6d6d42f90482cd Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Tue, 28 Mar 2017 14:05:22 +0200 Subject: [PATCH 1/5] Poll details based on nodeKind --- js/src/redux/providers/status.js | 69 ++++++++++++++++--------- js/src/redux/providers/statusReducer.js | 2 + 2 files changed, 48 insertions(+), 23 deletions(-) diff --git a/js/src/redux/providers/status.js b/js/src/redux/providers/status.js index dc965893fbb..76d8f38a7d4 100644 --- a/js/src/redux/providers/status.js +++ b/js/src/redux/providers/status.js @@ -149,7 +149,8 @@ export default class Status { } _pollTraceMode = () => { - return this._api.trace.block() + return this._api.trace + .block() .then(blockTraces => { // Assumes not in Trace Mode if no transactions // in latest block... @@ -272,23 +273,33 @@ export default class Status { this._timeoutIds.longStatus = setTimeout(() => this._pollLongStatus(), timeout); }; - // Poll Miner settings just in case - const minerPromise = this._pollMinerSettings(); - - const mainPromise = Promise - .all([ - this._api.parity.netPeers(), - this._api.web3.clientVersion(), - this._api.net.version(), + let minerPromise = null; + const { nodeKindFull } = this._store.getState().nodeStatus; + const promises = [ + this._api.web3.clientVersion(), + this._api.net.version(), + this._api.parity.netPeers(), + this._api.parity.nodeKind() + ]; + + // only check for upgrade & miner when running a full node + if (nodeKindFull) { + Array.prototype.push.apply(promises, [ this._api.parity.defaultExtraData(), + this._api.parity.enode().then((enode) => enode).catch(() => '-'), this._api.parity.netChain(), this._api.parity.netPort(), this._api.parity.rpcSettings(), - this._api.parity.enode().then((enode) => enode).catch(() => '-'), this._upgradeStore.checkUpgrade() - ]) + ]); + minerPromise = this._pollMinerSettings(); + } + + const mainPromise = Promise + .all(promises) .then(([ - netPeers, clientVersion, netVersion, defaultExtraData, netChain, netPort, rpcSettings, enode, upgradeStatus + clientVersion, netVersion, netPeers, nodeKind, // default + defaultExtraData, enode, netChain, netPort, rpcSettings // optional ]) => { const isTest = [ '2', // morden @@ -296,17 +307,29 @@ export default class Status { '42' // kovan ].includes(netVersion); - const longStatus = { - netPeers, - clientVersion, - defaultExtraData, - netChain, - netPort, - netVersion, - rpcSettings, - isTest, - enode - }; + const nodeKindFull = nodeKind && + nodeKind.availability === 'personal' && + nodeKind.capability === 'full'; + + const longStatus = Object.assign( + { + clientVersion, + isTest, + netVersion, + netPeers, + nodeKind, + nodeKindFull + }, + nodeKindFull + ? { + defaultExtraData, + enode, + netChain, + netPort, + rpcSettings + } + : {} + ); if (!isEqual(longStatus, this._longStatus)) { this._store.dispatch(statusCollection(longStatus)); diff --git a/js/src/redux/providers/statusReducer.js b/js/src/redux/providers/statusReducer.js index 1189f51c69e..7a8d77e5a20 100644 --- a/js/src/redux/providers/statusReducer.js +++ b/js/src/redux/providers/statusReducer.js @@ -41,6 +41,8 @@ const initialState = { }, netPort: new BigNumber(0), netVersion: '0', + nodeKind: null, + nodeKindFull: false, rpcSettings: {}, syncing: true, isConnected: false, From d50658fa26ef1d430caa0dce08b589697655c1b4 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Wed, 29 Mar 2017 15:42:52 +0200 Subject: [PATCH 2/5] Delay long polling when public/light --- js/src/redux/providers/status.js | 47 ++++++++++++++++--------- js/src/redux/providers/statusReducer.js | 2 ++ 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/js/src/redux/providers/status.js b/js/src/redux/providers/status.js index 0fa354d1a67..19bec2c0ac4 100644 --- a/js/src/redux/providers/status.js +++ b/js/src/redux/providers/status.js @@ -156,7 +156,8 @@ export default class Status { } _pollTraceMode = () => { - return this._api.trace.block() + return this._api.trace + .block() .then(blockTraces => { // Assumes not in Trace Mode if no transactions // in latest block... @@ -168,14 +169,12 @@ export default class Status { getApiStatus = () => { const { isConnected, isConnecting, needsToken, secureToken } = this._api; - const apiStatus = { + return { isConnected, isConnecting, needsToken, secureToken }; - - return apiStatus; } _pollStatus = () => { @@ -194,7 +193,10 @@ export default class Status { return Promise.resolve(); } - const statusPromises = [ this._api.eth.syncing(), this._api.parity.netPeers() ]; + const statusPromises = [ + this._api.eth.syncing(), + this._api.parity.netPeers() + ]; return Promise .all(statusPromises) @@ -225,7 +227,10 @@ export default class Status { return Promise.resolve(); } - const nextTimeout = (timeout = 30000) => { + const { nodeKindFull } = this._store.getState().nodeStatus; + const defaultTimeout = (nodeKindFull === false ? 240 : 30) * 1000; + + const nextTimeout = (timeout = defaultTimeout) => { if (this._timeoutIds.longStatus) { clearTimeout(this._timeoutIds.longStatus); } @@ -233,24 +238,34 @@ export default class Status { this._timeoutIds.longStatus = setTimeout(() => this._pollLongStatus(), timeout); }; + const statusPromises = [ + this._api.parity.nodeKind(), + this._api.parity.netPeers(), + this._api.web3.clientVersion(), + this._api.net.version(), + this._api.parity.netChain() + ]; + + if (nodeKindFull) { + statusPromises.push(this._upgradeStore.checkUpgrade()); + } + return Promise - .all([ - this._api.parity.netPeers(), - this._api.web3.clientVersion(), - this._api.net.version(), - this._api.parity.netChain(), - this._upgradeStore.checkUpgrade() - ]) - .then(([ - netPeers, clientVersion, netVersion, netChain, upgradeStatus - ]) => { + .all(statusPromises) + .then(([nodeKind, netPeers, clientVersion, netVersion, netChain]) => { const isTest = [ '2', // morden '3', // ropsten '42' // kovan ].includes(netVersion); + const nodeKindFull = nodeKind && + nodeKind.availability === 'personal' && + nodeKind.capability === 'full'; + const longStatus = { + nodeKind, + nodeKindFull, netPeers, clientVersion, netChain, diff --git a/js/src/redux/providers/statusReducer.js b/js/src/redux/providers/statusReducer.js index 6f509735ec9..12fe9654d8d 100644 --- a/js/src/redux/providers/statusReducer.js +++ b/js/src/redux/providers/statusReducer.js @@ -31,6 +31,8 @@ const initialState = { peers: [] }, netVersion: '0', + nodeKind: null, + nodeKindFull: null, syncing: true, isConnected: false, isConnecting: false, From 3ab7b76652cb5345762753119593f7a69fee91be Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Wed, 29 Mar 2017 15:43:08 +0200 Subject: [PATCH 3/5] Reload UI when nodeKind changed --- js/src/redux/providers/chainMiddleware.js | 36 +++++++++++++---------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/js/src/redux/providers/chainMiddleware.js b/js/src/redux/providers/chainMiddleware.js index 2df40ed8680..8fe8bb788db 100644 --- a/js/src/redux/providers/chainMiddleware.js +++ b/js/src/redux/providers/chainMiddleware.js @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import BalancesProvider from './balances'; -import { showSnackbar } from './snackbarActions'; import { DEFAULT_NETCHAIN } from './statusReducer'; export default class ChainMiddleware { @@ -24,20 +22,28 @@ export default class ChainMiddleware { if (action.type === 'statusCollection') { const { collection } = action; - if (collection && collection.netChain) { + if (collection) { const newChain = collection.netChain; - const { nodeStatus } = store.getState(); - - if (newChain !== nodeStatus.netChain && nodeStatus.netChain !== DEFAULT_NETCHAIN) { - store.dispatch(showSnackbar(`Switched to ${newChain}. The UI will reload now...`)); - setTimeout(() => { - window.location.reload(); - }, 0); - - // Fetch the new balances without notifying the user of any change - BalancesProvider.get(store).fetchAllBalances({ - changedNetwork: true - }); + const newNodeKind = collection.nodeKind; + + if (newChain) { + const { nodeStatus } = store.getState(); + const { netChain, nodeKind } = nodeStatus; + + // force reload when chain has changed + let forceReload = newChain !== netChain && netChain !== DEFAULT_NETCHAIN; + + // force reload when nodeKind (availability/capability) has changed + if (!forceReload && collection.nodeKind !== null && nodeKind !== null) { + forceReload = nodeKind.availability !== newNodeKind.availability || + nodeKind.capability !== newNodeKind.capability; + } + + if (forceReload) { + setTimeout(() => { + window.location.reload(); + }, 0); + } } } } From cef86714aaa1ff85e04b7495a7c41210fdedaddb Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Wed, 29 Mar 2017 16:30:36 +0200 Subject: [PATCH 4/5] Fix tests (not using dispatch, reload instead) --- .../redux/providers/chainMiddleware.spec.js | 37 +++++++++++++++---- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/js/src/redux/providers/chainMiddleware.spec.js b/js/src/redux/providers/chainMiddleware.spec.js index 50a25caf60d..837031c29f9 100644 --- a/js/src/redux/providers/chainMiddleware.spec.js +++ b/js/src/redux/providers/chainMiddleware.spec.js @@ -24,11 +24,22 @@ import { createWsApi } from '~/../test/e2e/ethapi'; let middleware; let next; let store; +let clock; const api = createWsApi(); Contracts.create(api); +function stubGlobals () { + clock = sinon.useFakeTimers(); + sinon.spy(window.location, 'reload'); +} + +function restoreGlobals () { + window.location.reload.restore(); + clock.restore(); +} + function createMiddleware (collection = {}) { middleware = new ChainMiddleware().toMiddleware(); next = sinon.stub(); @@ -46,10 +57,22 @@ function createMiddleware (collection = {}) { } function callMiddleware (action) { - return middleware(store)(next)(action); + const result = middleware(store)(next)(action); + + clock.tick(100); + + return result; } describe('reduxs/providers/ChainMiddleware', () => { + beforeEach(() => { + stubGlobals(); + }); + + afterEach(() => { + restoreGlobals(); + }); + describe('next action', () => { beforeEach(() => { createMiddleware(); @@ -69,25 +92,25 @@ describe('reduxs/providers/ChainMiddleware', () => { }); describe('chain switching', () => { - it('does not dispatch when moving from the initial/unknown chain', () => { + it('does not reload when moving from the initial/unknown chain', () => { createMiddleware(); callMiddleware({ type: 'statusCollection', collection: { netChain: 'homestead' } }); - expect(store.dispatch).not.to.have.been.called; + expect(window.location.reload).not.to.have.been.called; }); - it('does not dispatch when moving to the same chain', () => { + it('does not reload when moving to the same chain', () => { createMiddleware({ netChain: 'homestead' }); callMiddleware({ type: 'statusCollection', collection: { netChain: 'homestead' } }); - expect(store.dispatch).not.to.have.been.called; + expect(window.location.reload).not.to.have.been.called; }); - it('does dispatch when moving between chains', () => { + it('does reload when moving between chains', () => { createMiddleware({ netChain: 'homestead' }); callMiddleware({ type: 'statusCollection', collection: { netChain: 'ropsten' } }); - expect(store.dispatch).to.have.been.called; + expect(window.location.reload).to.have.been.called; }); }); }); From 51d8161fba5161dfbdc048b9066137e9a21dc205 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Wed, 19 Apr 2017 10:47:11 +0200 Subject: [PATCH 5/5] PR grumbles/cleanups --- js/src/redux/providers/chainMiddleware.js | 40 +++++++++++++---------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/js/src/redux/providers/chainMiddleware.js b/js/src/redux/providers/chainMiddleware.js index 8fe8bb788db..398e604be64 100644 --- a/js/src/redux/providers/chainMiddleware.js +++ b/js/src/redux/providers/chainMiddleware.js @@ -23,27 +23,33 @@ export default class ChainMiddleware { const { collection } = action; if (collection) { + const { nodeStatus } = store.getState(); + const { netChain, nodeKind } = nodeStatus; const newChain = collection.netChain; const newNodeKind = collection.nodeKind; + let reloadChain = false; + let reloadType = false; + // force reload when chain has changed and is not initial value if (newChain) { - const { nodeStatus } = store.getState(); - const { netChain, nodeKind } = nodeStatus; - - // force reload when chain has changed - let forceReload = newChain !== netChain && netChain !== DEFAULT_NETCHAIN; - - // force reload when nodeKind (availability/capability) has changed - if (!forceReload && collection.nodeKind !== null && nodeKind !== null) { - forceReload = nodeKind.availability !== newNodeKind.availability || - nodeKind.capability !== newNodeKind.capability; - } - - if (forceReload) { - setTimeout(() => { - window.location.reload(); - }, 0); - } + const hasChainChanged = newChain !== netChain; + const isInitialChain = netChain === DEFAULT_NETCHAIN; + + reloadChain = !isInitialChain && hasChainChanged; + } + + // force reload when nodeKind (availability or capability) has changed + if (newNodeKind && nodeKind) { + const hasAvailabilityChanged = nodeKind.availability !== newNodeKind.availability; + const hasCapabilityChanged = nodeKind.capability !== newNodeKind.capability; + + reloadType = hasAvailabilityChanged || hasCapabilityChanged; + } + + if (reloadChain || reloadType) { + setTimeout(() => { + window.location.reload(); + }, 0); } } }