Skip to content
This repository has been archived by the owner on Nov 17, 2023. It is now read-only.

Commit

Permalink
perf(wallet): pagination for onchain transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
mrfelton committed Oct 10, 2020
1 parent 04e01e0 commit 4b6a4e2
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 8 deletions.
8 changes: 6 additions & 2 deletions renderer/reducers/activity/reducer.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { send } from 'redux-electron-ipc'
import groupBy from 'lodash/groupBy'
import range from 'lodash/range'
import createReducer from '@zap/utils/createReducer'
import { getIntl } from '@zap/i18n'
import { mainLog } from '@zap/utils/log'
Expand All @@ -11,6 +10,7 @@ import { receiveInvoices } from 'reducers/invoice'
import { settingsSelectors } from 'reducers/settings'
import { fetchBalance } from 'reducers/balance'
import { fetchChannels } from 'reducers/channels'
import { fetchInfo, infoSelectors } from 'reducers/info'
import { showError, showNotification } from 'reducers/notification'
import { createActivityPaginator, getItemType } from './utils'
import { hasNextPage } from './selectors'
Expand Down Expand Up @@ -240,18 +240,22 @@ export const resetPaginator = () => () => {
* @returns {(dispatch:Function, getState:Function) => Promise<void>} Thunk
*/
export const loadPage = (reload = false) => async (dispatch, getState) => {
await dispatch(fetchInfo())
const config = settingsSelectors.currentConfig(getState())
const blockHeight = infoSelectors.blockHeight(getState())
const thisPaginator = getPaginator()

if (reload || hasNextPage(getState())) {
const { pageSize } = config.activity
const { items, hasNextPage: paginatorHasNextPage } = await thisPaginator(pageSize)
const { items, hasNextPage: paginatorHasNextPage } = await thisPaginator(pageSize, blockHeight)

if (!reload) {
loadedPages += 1
dispatch({ type: SET_HAS_NEXT_PAGE, value: paginatorHasNextPage })
}

const { invoices, payments, transactions } = groupBy(items, getItemType)

invoices && dispatch(receiveInvoices(invoices))
payments && dispatch(receivePayments(payments))
transactions && dispatch(receiveTransactions(transactions))
Expand Down
19 changes: 16 additions & 3 deletions renderer/reducers/activity/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,22 @@ export const createActivityPaginator = () => {
return { items: payments, offset: parseInt(firstIndexOffset || 0, 10) }
}

const fetchTransactions = async () => {
const { transactions } = await grpc.services.Lightning.getTransactions()
return { items: transactions, offset: 0 }
const fetchTransactions = async (pageSize, offset, blockHeight) => {
// Lets load 10x more bloks that page size is set to since blocks only cover a 10 minute period.
const vPagesize = pageSize * 5

// Determine start point.
const firstStart = blockHeight - vPagesize
const nextStart = offset - vPagesize
const startHeight = offset === 0 ? firstStart : nextStart

// Determine end height.
const endHeight = offset || -1
const { transactions } = await grpc.services.Lightning.getTransactions({
startHeight,
endHeight,
})
return { items: transactions, offset: startHeight }
}

const getTimestamp = item =>
Expand Down
9 changes: 9 additions & 0 deletions renderer/reducers/info/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ const isSyncedToChain = state => get(state, 'info.data.syncedToChain', false)
*/
const isSyncedToGraph = state => get(state, 'info.data.syncedToGraph', false)

/**
* blockHeight - Block height.
*
* @param {State} state Redux state
* @returns {number} Current block height
*/
const blockHeight = state => get(state, 'info.data.blockHeight')

/**
* version - Node version.
*
Expand Down Expand Up @@ -230,6 +238,7 @@ const chainName = createSelector(chainSelector, chainsSelector, (chain, chains)
)

export default {
blockHeight,
chainSelector,
chainsSelector,
networkSelector,
Expand Down
9 changes: 6 additions & 3 deletions utils/pagination.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default function combinePaginators(itemSorter, ...paginators) {
// pagination tip fo reach of `paginators`
const offsets = new Map()

return async pageSize => {
return async (pageSize, blockHeight) => {
// splits `items` into two parts - result and rest based on`pageSize`
// rest is a leftover which should be merged into cache
const splitResult = (...items) => {
Expand All @@ -34,7 +34,7 @@ export default function combinePaginators(itemSorter, ...paginators) {
const depleted = { offset: 0, items: [] }
const missing = { offset: 1, items: [] }
const next = p =>
p(pageSize, offsets.get(p) || 0).catch(e => {
p(pageSize, offsets.get(p) || 0, blockHeight).catch(e => {
mainLog.error('Unable to fetch activity items from %s paginator: %o', p.name, e)
return missing
})
Expand All @@ -44,7 +44,10 @@ export default function combinePaginators(itemSorter, ...paginators) {
// returns true if some of the paginators have next page
const hasNextPage = () => [...offsets.values()].find(Boolean)
// prepares function result
const createResult = items => ({ items, hasNextPage: Boolean(cache.length || hasNextPage()) })
const createResult = items => ({
items,
hasNextPage: Boolean(cache.length || hasNextPage()),
})

const current = await fetchNextPage()

Expand Down

0 comments on commit 4b6a4e2

Please sign in to comment.