diff --git a/app/src/renderer/components/common/NiDataLoading.vue b/app/src/renderer/components/common/NiDataLoading.vue index 940d206bd6..0f61b4e545 100644 --- a/app/src/renderer/components/common/NiDataLoading.vue +++ b/app/src/renderer/components/common/NiDataLoading.vue @@ -1,6 +1,6 @@ @@ -8,6 +8,12 @@ data-msg(icon="rotate_right" spin="true") import DataMsg from 'common/NiDataMsg' export default { name: 'ni-data-loading', - components: { DataMsg } + components: { DataMsg }, + props: { + title: { + type: String, + default: 'Data is loadingā€¦' + } + } } diff --git a/app/src/renderer/components/monitor/PageBlocks.vue b/app/src/renderer/components/monitor/PageBlocks.vue index b1b8a1ca8e..a0a37a5a3c 100644 --- a/app/src/renderer/components/monitor/PageBlocks.vue +++ b/app/src/renderer/components/monitor/PageBlocks.vue @@ -7,7 +7,8 @@ page(title='Block Explorer') modal-search(type="blocks") - data-loading(v-if="!blockchain.subscription") + data-loading(v-if="blockchain.syncing" title="Node is syncing blockchainā€¦") + data-loading(v-if="!blockchain.syncing && !blockchain.subscription") part(title='Current Block' v-if="blockchain.subscription") list-item(dt='Block Height' :dd='num.prettyInt(lastHeader.height)' :to="{ name: 'block', params: { block: lastHeader.height} }") diff --git a/app/src/renderer/vuex/modules/blockchain.js b/app/src/renderer/vuex/modules/blockchain.js index a5d064c64f..f217a645ee 100644 --- a/app/src/renderer/vuex/modules/blockchain.js +++ b/app/src/renderer/vuex/modules/blockchain.js @@ -6,6 +6,7 @@ export default ({ commit, node }) => { blockHeight: null, // we remember the height so we can requery the block, if querying failed blockLoading: false, subscription: false, + syncing: true, blockMetas: [] } @@ -69,21 +70,39 @@ export default ({ commit, node }) => { blockMetaInfo && state.blockMetas.push(blockMetaInfo) return blockMetaInfo }, - subscribeToBlocks ({ commit }) { - node.rpc.subscribe({ query: "tm.event = 'NewBlock'" }, (err, event) => { - state.subscription = true + subscribeToBlocks ({ state, commit, dispatch }) { + // ensure we never subscribe twice + if (state.subscription) return - if (err) { + function error (err) { + state.subscription = false + commit('notifyError', { title: `Error subscribing to new blocks`, body: err.message }) + } + + node.rpc.status((err, status) => { + if (err) return error(err) + + if (status.syncing) { + // still syncing, let's try subscribing again in 30 seconds + state.syncing = true state.subscription = false - commit('notifyError', { title: `Error subscribing to new blocks`, body: err.message }) + setTimeout(() => dispatch('subscribeToBlocks'), 30e3) return } - state.blocks.unshift(event.data.data.block) + state.syncing = false - if (state.blocks.length === 20) { - state.blocks.pop() - } + node.rpc.subscribe({ query: "tm.event = 'NewBlock'" }, (err, event) => { + state.subscription = true + + if (err) return error(err) + + state.blocks.unshift(event.data.data.block) + + if (state.blocks.length === 20) { + state.blocks.pop() + } + }) }) } } diff --git a/test/unit/specs/components/monitor/__snapshots__/PageBlocks.spec.js.snap b/test/unit/specs/components/monitor/__snapshots__/PageBlocks.spec.js.snap index dcd2581d3b..e79d2d9323 100644 --- a/test/unit/specs/components/monitor/__snapshots__/PageBlocks.spec.js.snap +++ b/test/unit/specs/components/monitor/__snapshots__/PageBlocks.spec.js.snap @@ -45,6 +45,7 @@ exports[`PageBlocks has the expected html structure 1`] = `
+
diff --git a/test/unit/specs/store/blockchain.spec.js b/test/unit/specs/store/blockchain.spec.js index 6e7075ba0e..af35c388fb 100644 --- a/test/unit/specs/store/blockchain.spec.js +++ b/test/unit/specs/store/blockchain.spec.js @@ -149,4 +149,22 @@ describe('Module: Blockchain', () => { expect(store.state.blockchain.blocks.length).toBe(0) expect(store.state.notifications[0].title).toContain(`Error subscribing to new blocks`) }) + + it('should not subscribe if still syncing', async () => { + node.rpc.status = (cb) => { + cb(null, { syncing: true }) + } + node.rpc.subscribe = jest.fn() + store.dispatch('subscribeToBlocks') + expect(node.rpc.subscribe.mock.calls.length).toBe(0) + }) + + it('should subscribe if not syncing', async () => { + node.rpc.status = (cb) => { + cb(null, { syncing: false }) + } + node.rpc.subscribe = jest.fn() + store.dispatch('subscribeToBlocks') + expect(node.rpc.subscribe.mock.calls.length).toBe(1) + }) })