diff --git a/src/bridge/BridgeSyncContext.js b/src/bridge/BridgeSyncContext.js index dcba6613..e8df3923 100644 --- a/src/bridge/BridgeSyncContext.js +++ b/src/bridge/BridgeSyncContext.js @@ -45,6 +45,7 @@ export type BehaviorAction = | { type: 'BACKGROUND_TICK' } | { type: 'SET_SKIP_UNDER_PRIORITY', priority: number } | { type: 'SYNC_ONE_ACCOUNT', accountId: string, priority: number } + | { type: 'SYNC_SOME_ACCOUNTS', accountIds: string[], priority: number } | { type: 'SYNC_ALL_ACCOUNTS', priority: number } export type Sync = (action: BehaviorAction) => void @@ -64,7 +65,6 @@ const actions = { class Provider extends Component { constructor() { super() - const synchronize = (accountId: string, next: () => void) => { const state = syncStateLocalSelector(this.props.bridgeSync, { accountId }) if (state.pending) { @@ -104,6 +104,7 @@ class Provider extends Component { const schedule = (ids: string[], priority: number) => { if (priority < skipUnderPriority) return // by convention we remove concurrent tasks with same priority + // FIXME this is somehow a hack. ideally we should just dedup the account ids in the pending queue... syncQueue.remove(o => priority === o.priority) syncQueue.push(ids, -priority) } @@ -131,6 +132,10 @@ class Provider extends Component { SYNC_ONE_ACCOUNT: ({ accountId, priority }) => { schedule([accountId], priority) }, + + SYNC_SOME_ACCOUNTS: ({ accountIds, priority }) => { + schedule(accountIds, priority) + }, } const sync = (action: BehaviorAction) => { diff --git a/src/components/SyncContinouslyPendingOperations.js b/src/components/SyncContinouslyPendingOperations.js new file mode 100644 index 00000000..764f2732 --- /dev/null +++ b/src/components/SyncContinouslyPendingOperations.js @@ -0,0 +1,65 @@ +// @flow +// Sync continuously the accounts that have pending operations + +import React, { Component } from 'react' +import logger from 'logger' +import { createStructuredSelector, createSelector } from 'reselect' +import { connect } from 'react-redux' +import type { Account } from '@ledgerhq/live-common/lib/types' +import { BridgeSyncConsumer } from 'bridge/BridgeSyncContext' +import type { Sync } from 'bridge/BridgeSyncContext' +import { accountsSelector } from 'reducers/accounts' + +const accountsWithPendingOperationsSelector = createSelector(accountsSelector, accounts => + accounts.filter(a => a.pendingOperations.length > 0), +) + +class SyncContPendingOpsConnected extends Component<{ + sync: Sync, + accounts: Account[], + priority: number, + interval: number, +}> { + componentDidMount() { + this.timeout = setTimeout(this.check, this.props.interval) + } + componentWillUnmount() { + clearTimeout(this.timeout) + } + check = () => { + const { sync, accounts, priority, interval } = this.props + setTimeout(this.check, interval) + if (accounts.length > 0) { + logger.log(`SyncContinouslyPendingOperations: found ${accounts.length} accounts`, accounts) + sync({ + type: 'SYNC_SOME_ACCOUNTS', + accountIds: accounts.map(a => a.id), + priority, + }) + } + } + timeout: * + render() { + return null + } +} + +const Effect = connect( + createStructuredSelector({ + accounts: accountsWithPendingOperationsSelector, + }), +)(SyncContPendingOpsConnected) + +const SyncContinuouslyPendingOperations = ({ + priority, + interval, +}: { + priority: number, + interval: number, +}) => ( + + {sync => } + +) + +export default SyncContinuouslyPendingOperations diff --git a/src/components/layout/Default.js b/src/components/layout/Default.js index 393c91f7..d12f38bf 100644 --- a/src/components/layout/Default.js +++ b/src/components/layout/Default.js @@ -5,6 +5,7 @@ import { compose } from 'redux' import styled from 'styled-components' import { Route, withRouter } from 'react-router' import { translate } from 'react-i18next' +import { SYNC_PENDING_INTERVAL } from 'config/constants' import type { Location } from 'react-router' @@ -26,6 +27,7 @@ import AppRegionDrag from 'components/AppRegionDrag' import IsUnlocked from 'components/IsUnlocked' import SideBar from 'components/MainSideBar' import TopBar from 'components/TopBar' +import SyncContinuouslyPendingOperations from '../SyncContinouslyPendingOperations' const Main = styled(GrowScroll).attrs({ px: 6, @@ -83,6 +85,8 @@ class Default extends Component { ))} + +
diff --git a/src/config/constants.js b/src/config/constants.js index 43007d85..78b564f7 100644 --- a/src/config/constants.js +++ b/src/config/constants.js @@ -35,6 +35,7 @@ export const LISTEN_DEVICES_POLLING_INTERVAL = intFromEnv('LISTEN_DEVICES_POLLIN export const OUTDATED_CONSIDERED_DELAY = intFromEnv('OUTDATED_CONSIDERED_DELAY', 5 * 60 * 1000) export const SYNC_ALL_INTERVAL = 120 * 1000 export const SYNC_BOOT_DELAY = 2 * 1000 +export const SYNC_PENDING_INTERVAL = 10 * 1000 export const SYNC_MAX_CONCURRENT = intFromEnv('LEDGER_SYNC_MAX_CONCURRENT', 1) export const SYNC_TIMEOUT = intFromEnv('SYNC_TIMEOUT', 30 * 1000)