diff --git a/backend/src/api/bitcoin/bitcoin-api-abstract-factory.ts b/backend/src/api/bitcoin/bitcoin-api-abstract-factory.ts index c44653a3d..bd779a4af 100644 --- a/backend/src/api/bitcoin/bitcoin-api-abstract-factory.ts +++ b/backend/src/api/bitcoin/bitcoin-api-abstract-factory.ts @@ -25,6 +25,7 @@ export interface AbstractBitcoinApi { $getBatchedOutspends(txId: string[]): Promise; startHealthChecks(): void; + isFailedOver(): boolean; } export interface BitcoinRpcCredentials { host: string; diff --git a/backend/src/api/bitcoin/bitcoin-api.ts b/backend/src/api/bitcoin/bitcoin-api.ts index 807baae2e..15f475b39 100644 --- a/backend/src/api/bitcoin/bitcoin-api.ts +++ b/backend/src/api/bitcoin/bitcoin-api.ts @@ -356,6 +356,9 @@ class BitcoinApi implements AbstractBitcoinApi { } public startHealthChecks(): void {}; + public isFailedOver(): boolean { + return false; + } } export default BitcoinApi; diff --git a/backend/src/api/bitcoin/esplora-api.ts b/backend/src/api/bitcoin/esplora-api.ts index d6d4327cb..0f0b19a94 100644 --- a/backend/src/api/bitcoin/esplora-api.ts +++ b/backend/src/api/bitcoin/esplora-api.ts @@ -17,6 +17,8 @@ interface FailoverHost { } class FailoverRouter { + isFailedOver: boolean = false; + preferredHost: FailoverHost; activeHost: FailoverHost; fallbackHost: FailoverHost; hosts: FailoverHost[]; @@ -46,6 +48,7 @@ class FailoverRouter { socket: !!config.ESPLORA.UNIX_SOCKET_PATH, preferred: true, }; + this.preferredHost = this.activeHost; this.fallbackHost = this.activeHost; this.hosts.unshift(this.activeHost); this.multihost = this.hosts.length > 1; @@ -151,6 +154,7 @@ class FailoverRouter { this.sortHosts(); this.activeHost = this.hosts[0]; logger.warn(`Switching esplora host to ${this.activeHost.host}`); + this.isFailedOver = this.activeHost !== this.preferredHost; } private addFailure(host: FailoverHost): FailoverHost { @@ -302,6 +306,10 @@ class ElectrsApi implements AbstractBitcoinApi { public startHealthChecks(): void { this.failoverRouter.startHealthChecks(); } + + public isFailedOver(): boolean { + return this.failoverRouter.isFailedOver; + } } export default ElectrsApi; diff --git a/backend/src/api/mempool.ts b/backend/src/api/mempool.ts index 73260dc9e..7ea96625a 100644 --- a/backend/src/api/mempool.ts +++ b/backend/src/api/mempool.ts @@ -26,6 +26,9 @@ class Mempool { private accelerations: { [txId: string]: Acceleration } = {}; + private failoverTimes: number[] = []; + private statisticsPaused: boolean = false; + private txPerSecondArray: number[] = []; private txPerSecond: number = 0; @@ -164,6 +167,10 @@ class Mempool { return this.mempoolInfo; } + public getStatisticsIsPaused(): boolean { + return this.statisticsPaused; + } + public getTxPerSecond(): number { return this.txPerSecond; } @@ -242,6 +249,10 @@ class Mempool { logger.debug(`fetched ${txs.length} transactions`); this.updateTimerProgress(timer, 'fetched new transactions'); + if (bitcoinApi.isFailedOver()) { + this.failoverTimes.push(Date.now()); + } + for (const transaction of txs) { this.mempoolCache[transaction.txid] = transaction; if (this.inSync) { @@ -259,6 +270,10 @@ class Mempool { } } + if (bitcoinApi.isFailedOver()) { + this.failoverTimes.push(Date.now()); + } + if (txs.length < slice.length) { const missing = slice.length - txs.length; if (config.MEMPOOL.BACKEND === 'esplora') { @@ -491,6 +506,10 @@ class Mempool { private updateTxPerSecond() { const nowMinusTimeSpan = new Date().getTime() - (1000 * config.STATISTICS.TX_PER_SECOND_SAMPLE_PERIOD); + + this.failoverTimes = this.failoverTimes.filter((unixTime) => unixTime > nowMinusTimeSpan); + this.statisticsPaused = this.failoverTimes.length > 0; + this.txPerSecondArray = this.txPerSecondArray.filter((unixTime) => unixTime > nowMinusTimeSpan); this.txPerSecond = this.txPerSecondArray.length / config.STATISTICS.TX_PER_SECOND_SAMPLE_PERIOD || 0; diff --git a/backend/src/api/statistics/statistics.ts b/backend/src/api/statistics/statistics.ts index 27554f36d..6cdc8dc1f 100644 --- a/backend/src/api/statistics/statistics.ts +++ b/backend/src/api/statistics/statistics.ts @@ -29,9 +29,10 @@ class Statistics { } private async runStatistics(): Promise { - if (!memPool.isInSync()) { + if (!memPool.isInSync() || memPool.getStatisticsIsPaused()) { return; } + const currentMempool = memPool.getMempool(); const txPerSecond = memPool.getTxPerSecond(); const vBytesPerSecond = memPool.getVBytesPerSecond(); diff --git a/backend/src/api/websocket-handler.ts b/backend/src/api/websocket-handler.ts index 41cb6b99c..5cabdb2b3 100644 --- a/backend/src/api/websocket-handler.ts +++ b/backend/src/api/websocket-handler.ts @@ -73,7 +73,7 @@ class WebsocketHandler { const da = difficultyAdjustment.getDifficultyAdjustment(); this.updateSocketDataFields({ 'mempoolInfo': memPool.getMempoolInfo(), - 'vBytesPerSecond': memPool.getVBytesPerSecond(), + 'vBytesPerSecond': memPool.getStatisticsIsPaused() ? null : memPool.getVBytesPerSecond(), 'blocks': _blocks, 'conversions': priceUpdater.getLatestPrices(), 'mempool-blocks': mempoolBlocks.getMempoolBlocks(),