feat: standardize balance memoizing speed

feat: add infura-only override for getStatus()
fix: remove coin filtering on poller
feat: add getStatus() response caching on infura
This commit is contained in:
Sérgio Salgado 2022-07-06 14:48:49 +01:00
parent 2d5cbe771a
commit d6bc692af4
5 changed files with 99 additions and 44 deletions

View file

@ -1,5 +1,9 @@
const _ = require('lodash/fp')
const base = require('../geth/base')
const T = require('../../../time')
const { BALANCE_FETCH_SPEED_MULTIPLIER } = require('../../../constants')
const REGULAR_TX_POLLING = 5 * T.seconds
const NAME = 'infura'
@ -12,4 +16,60 @@ function run (account) {
base.connect(endpoint)
}
module.exports = _.merge(base, { NAME, run })
const txsCache = {}
setInterval(() => {
_.forEach(it => {
// A transaction not being updated for over an hour means that it stopped being fetched on poll,
// which means that it probably was cancelled by the operator or something else caused the
// transaction to stop being listened to. So, trim the cache to save memory
const lastReq = _.isNil(txsCache[it].lastReqTime) ? Date.now() : new Date(txsCache[it].lastReqTime)
const timePassedSinceReq = Date.now() - lastReq
if (timePassedSinceReq > T.hour) delete txsCache[it]
}, _.keys(txsCache))
}, T.minute)
function shouldGetStatus (tx) {
const timePassedSinceTx = Date.now() - new Date(tx.created)
const timePassedSinceReq = Date.now() - new Date(txsCache[tx.id].lastReqTime)
// Allow for infura to gradually lower the amount of requests based on the time passed since the transaction
// Until first 5 minutes - 1/2 regular polling speed
// Until first 10 minutes - 1/4 regular polling speed
// Until first hour - 1/8 polling speed
// Until first two hours - 1/12 polling speed
// Until first four hours - 1/16 polling speed
// Until first day - 1/24 polling speed
// After first day - 1/32 polling speed
if (timePassedSinceTx < 5 * T.minutes) return _.isNil(txsCache[tx.id].res) || timePassedSinceReq > 2 * REGULAR_TX_POLLING
if (timePassedSinceTx < 10 * T.minutes) return _.isNil(txsCache[tx.id].res) || timePassedSinceReq > 4 * REGULAR_TX_POLLING
if (timePassedSinceTx < 1 * T.hour) return _.isNil(txsCache[tx.id].res) || timePassedSinceReq > 8 * REGULAR_TX_POLLING
if (timePassedSinceTx < 2 * T.hours) return _.isNil(txsCache[tx.id].res) || timePassedSinceReq > 12 * REGULAR_TX_POLLING
if (timePassedSinceTx < 4 * T.hours) return _.isNil(txsCache[tx.id].res) || timePassedSinceReq > 16 * REGULAR_TX_POLLING
if (timePassedSinceTx < 1 * T.day) return _.isNil(txsCache[tx.id].res) || timePassedSinceReq > 24 * REGULAR_TX_POLLING
return _.isNil(txsCache[tx.id].res) || timePassedSinceReq > 32 * REGULAR_TX_POLLING
}
// Override geth's getStatus function to allow for different polling timing
function getStatus (account, tx, requested, settings, operatorId) {
if (_.isNil(txsCache[tx.id])) {
txsCache[tx.id] = { lastReqTime: Date.now() }
}
// return last available response
if (!shouldGetStatus(tx)) {
return Promise.resolve(txsCache[tx.id].res)
}
return base.getStatus(account, tx, requested, settings, operatorId)
.then(res => {
if (res.status === 'confirmed') {
delete txsCache[tx.id] // Transaction reached final status, can trim it from the caching obj
} else {
txsCache[tx.id].lastReqTime = Date.now()
txsCache[tx.id].res = res
}
return res
})
}
module.exports = _.merge(base, { NAME, run, getStatus, fetchSpeed: BALANCE_FETCH_SPEED_MULTIPLIER.SLOW })