From 5be5b682138353312fec161a33990839c5cfb296 Mon Sep 17 00:00:00 2001 From: nymkappa <1612910616@pm.me> Date: Sat, 19 Oct 2024 20:47:22 +0900 Subject: [PATCH 1/8] [accelerator] auto scroll when clicking on "Accelerate" CTA --- .../accelerate-checkout/accelerate-checkout.component.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.ts b/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.ts index e9888f58b..c92232478 100644 --- a/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.ts +++ b/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.ts @@ -223,6 +223,7 @@ export class AccelerateCheckout implements OnInit, OnDestroy { this.loadingBtcpayInvoice = true; this.invoice = null; this.requestBTCPayInvoice(); + this.scrollToElementWithTimeout('acceleratePreviewAnchor', 'start', 100); } else if (this._step === 'cashapp' && this.cashappEnabled) { this.loadingCashapp = true; this.setupSquare(); From 560b2b0e08f519b6d9b1a5bd50d4a43ae697dfeb Mon Sep 17 00:00:00 2001 From: nymkappa <1612910616@pm.me> Date: Sun, 20 Oct 2024 17:22:27 +0900 Subject: [PATCH 2/8] [accelerator] show acceleration count in aggregated history chart, show 1y history by default in dashboard --- .../acceleration-fees-graph.component.html | 6 - .../acceleration-fees-graph.component.ts | 137 ++++++++++-------- .../acceleration-stats.component.ts | 13 +- .../accelerator-dashboard.component.html | 16 +- .../accelerator-dashboard.component.ts | 2 +- 5 files changed, 95 insertions(+), 79 deletions(-) diff --git a/frontend/src/app/components/acceleration/acceleration-fees-graph/acceleration-fees-graph.component.html b/frontend/src/app/components/acceleration/acceleration-fees-graph/acceleration-fees-graph.component.html index 9146c8e34..114a20913 100644 --- a/frontend/src/app/components/acceleration/acceleration-fees-graph/acceleration-fees-graph.component.html +++ b/frontend/src/app/components/acceleration/acceleration-fees-graph/acceleration-fees-graph.component.html @@ -11,12 +11,6 @@
- - diff --git a/frontend/src/app/components/acceleration/acceleration-fees-graph/acceleration-fees-graph.component.ts b/frontend/src/app/components/acceleration/acceleration-fees-graph/acceleration-fees-graph.component.ts index 68a2bdd52..25dd59f76 100644 --- a/frontend/src/app/components/acceleration/acceleration-fees-graph/acceleration-fees-graph.component.ts +++ b/frontend/src/app/components/acceleration/acceleration-fees-graph/acceleration-fees-graph.component.ts @@ -1,5 +1,5 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, Input, LOCALE_ID, NgZone, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core'; -import { EChartsOption } from '../../../graphs/echarts'; +import { echarts, EChartsOption } from '../../../graphs/echarts'; import { Observable, Subject, Subscription, combineLatest, fromEvent, merge, share } from 'rxjs'; import { startWith, switchMap, tap } from 'rxjs/operators'; import { SeoService } from '../../../services/seo.service'; @@ -8,11 +8,10 @@ import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { download, formatterXAxis, formatterXAxisLabel, formatterXAxisTimeCategory } from '../../../shared/graphs.utils'; import { StorageService } from '../../../services/storage.service'; import { MiningService } from '../../../services/mining.service'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute } from '@angular/router'; import { Acceleration } from '../../../interfaces/node-api.interface'; import { ServicesApiServices } from '../../../services/services-api.service'; import { StateService } from '../../../services/state.service'; -import { RelativeUrlPipe } from '../../../shared/pipes/relative-url/relative-url.pipe'; @Component({ selector: 'app-acceleration-fees-graph', @@ -31,9 +30,9 @@ import { RelativeUrlPipe } from '../../../shared/pipes/relative-url/relative-url export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDestroy { @Input() widget: boolean = false; @Input() height: number = 300; - @Input() right: number | string = 45; - @Input() left: number | string = 75; - @Input() period: '24h' | '3d' | '1w' | '1m' | 'all' = '1w'; + @Input() right: number | string = 70; + @Input() left: number | string = 55; + @Input() period: '24h' | '1w' | '1m' | '1y' | 'all' = '1y'; @Input() accelerations$: Observable; miningWindowPreference: string; @@ -49,7 +48,7 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest isLoading = true; formatNumber = formatNumber; timespan = ''; - periodSubject$: Subject<'24h' | '3d' | '1w' | '1m' | 'all'> = new Subject(); + periodSubject$: Subject<'24h' | '1w' | '1m' | '1y' | 'all'> = new Subject(); chartInstance: any = undefined; daysAvailable: number = 0; @@ -62,9 +61,7 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest private miningService: MiningService, private route: ActivatedRoute, public stateService: StateService, - private cd: ChangeDetectorRef, - private router: Router, - private zone: NgZone, + private cd: ChangeDetectorRef ) { this.radioGroupForm = this.formBuilder.group({ dateSpan: '1w' }); this.radioGroupForm.controls.dateSpan.setValue('1w'); @@ -81,7 +78,7 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest this.radioGroupForm.controls.dateSpan.setValue(this.miningWindowPreference); this.route.fragment.subscribe((fragment) => { - if (['24h', '3d', '1w', '1m', '3m', 'all'].indexOf(fragment) > -1) { + if (['1w', '1m', '1y', 'all'].indexOf(fragment) > -1) { this.radioGroupForm.controls.dateSpan.setValue(fragment, { emitEvent: false }); } }); @@ -96,7 +93,9 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest if (!this.widget) { this.storageService.setValue('miningWindowPreference', timespan); } - this.isLoading = true; + if (timespan !== this.timespan) { + this.isLoading = true; + } this.timespan = timespan; return this.servicesApiService.getAggregatedAccelerationHistory$({timeframe: this.timespan}); }) @@ -118,6 +117,9 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest ngOnChanges(changes: SimpleChanges): void { if (changes.period) { + if (this.period === '24h') { + this.period = '1m'; + } this.periodSubject$.next(this.period); } } @@ -139,13 +141,19 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest this.chartOptions = { title: title, color: [ - '#8F5FF6', - '#6b6b6b', + new echarts.graphic.LinearGradient(0, 0, 0, 0.65, [ + { offset: 0, color: '#F4511E' }, + { offset: 0.25, color: '#FB8C00' }, + { offset: 0.5, color: '#FFB300' }, + { offset: 0.75, color: '#FDD835' }, + { offset: 1, color: '#7CB342' } + ]), + '#ab2dce', ], animation: false, grid: { - height: (this.widget && this.height) ? this.height - 30 : undefined, - top: this.widget ? 20 : 40, + height: (this.widget && this.height) ? this.height - 50 : undefined, + top: this.widget ? 40 : 60, bottom: this.widget ? 30 : 80, right: this.right, left: this.left, @@ -167,17 +175,18 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest formatter: (ticks) => { let tooltip = `${formatterXAxis(this.locale, this.timespan, parseInt(ticks[0].axisValue, 10))}
`; - if (ticks[0].data[1] > 10_000_000) { - tooltip += `${ticks[0].marker} ${ticks[0].seriesName}: ${formatNumber(ticks[0].data[1] / 100_000_000, this.locale, '1.0-8')} BTC
`; - } else { - tooltip += `${ticks[0].marker} ${ticks[0].seriesName}: ${formatNumber(ticks[0].data[1], this.locale, '1.0-0')} sats
`; - } - - if (['24h', '3d'].includes(this.timespan)) { - tooltip += `` + $localize`At block: ${ticks[0].data[2]}` + ``; - } else { - tooltip += `` + $localize`Around block: ${ticks[0].data[2]}` + ``; + for (const tick of ticks) { + if (tick.seriesName === 'Total bid boost') { + if (tick.data[1] > 10_000_000) { + tooltip += `${tick.marker} ${tick.seriesName}: ${formatNumber(tick.data[1] / 100_000_000, this.locale, '1.0-8')} BTC
`; + } else { + tooltip += `${tick.marker} ${tick.seriesName}: ${formatNumber(tick.data[1], this.locale, '1.0-0')} sats
`; + } + } else if (tick && tick.seriesName === 'Accelerated') { + tooltip += `${tick.marker} ${tick.seriesName}: ${formatNumber(tick.data[1], this.locale, '1.0-0')}
`; + } } + tooltip += `` + $localize`Around block: ${ticks[0].data[2]}` + ``; return tooltip; } @@ -209,6 +218,17 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest textStyle: { color: 'white', }, + itemStyle: { + color: '#FFB300', + }, + icon: 'roundRect', + }, + { + name: 'Accelerated', + inactiveColor: 'rgb(110, 112, 121)', + textStyle: { + color: 'white', + }, icon: 'roundRect', }, ], @@ -220,6 +240,13 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest yAxis: data.length === 0 ? undefined : [ { type: 'value', + name: 'Total bid boost', + position: 'right', + nameTextStyle: { + align: 'right', + padding: [0, -65, 0, 0], + fontStyle: 'italic', + }, axisLabel: { color: 'rgb(110, 112, 121)', formatter: (val) => { @@ -230,6 +257,20 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest } } }, + splitLine: null + }, + { + type: 'value', + name: 'Accelerated', + position: 'left', + axisLabel: { + color: 'rgb(110, 112, 121)', + }, + nameTextStyle: { + align: 'right', + padding: [0, -35, 0, 0], + fontStyle: 'italic', + }, splitLine: { lineStyle: { type: 'dotted', @@ -238,33 +279,28 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest } }, }, - { - type: 'value', - position: 'right', - axisLabel: { - color: 'rgb(110, 112, 121)', - formatter: function(val) { - return `${val}`; - }.bind(this) - }, - splitLine: { - show: false, - }, - }, ], series: data.length === 0 ? undefined : [ { - legendHoverLink: false, - zlevel: 1, name: 'Total bid boost', data: data.map(h => { return [h.timestamp * 1000, h.sumBidBoost, h.avgHeight] }), - stack: 'Total', + type: 'line', + symbol: 'none', + lineStyle: { + width: 1, + }, + smooth: true, + }, + { + name: 'Accelerated', + yAxisIndex: 1, + data: data.map(h => { + return [h.timestamp * 1000, h.count, h.avgHeight] + }), type: 'bar', barWidth: '90%', - large: true, - barMinHeight: 3, }, ], dataZoom: (this.widget || data.length === 0 )? undefined : [{ @@ -297,19 +333,6 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest onChartInit(ec) { this.chartInstance = ec; - - this.chartInstance.on('click', (e) => { - this.zone.run(() => { - if (['24h', '3d'].includes(this.timespan)) { - const url = new RelativeUrlPipe(this.stateService).transform(`/block/${e.data[2]}`); - if (e.event.event.shiftKey || e.event.event.ctrlKey || e.event.event.metaKey) { - window.open(url); - } else { - this.router.navigate([url]); - } - } - }); - }); } isMobile() { diff --git a/frontend/src/app/components/acceleration/acceleration-stats/acceleration-stats.component.ts b/frontend/src/app/components/acceleration/acceleration-stats/acceleration-stats.component.ts index 392f1392b..2d4640d0a 100644 --- a/frontend/src/app/components/acceleration/acceleration-stats/acceleration-stats.component.ts +++ b/frontend/src/app/components/acceleration/acceleration-stats/acceleration-stats.component.ts @@ -16,7 +16,7 @@ export type AccelerationStats = { changeDetection: ChangeDetectionStrategy.OnPush, }) export class AccelerationStatsComponent implements OnInit, OnChanges { - @Input() timespan: '24h' | '3d' | '1w' | '1m' | 'all' = '1w'; + @Input() timespan: '24h' | '1m' | '1y' | 'all' = '1y'; accelerationStats$: Observable; blocksInPeriod: number = 7 * 144; @@ -38,15 +38,12 @@ export class AccelerationStatsComponent implements OnInit, OnChanges { case '24h': this.blocksInPeriod = 144; break; - case '3d': - this.blocksInPeriod = 3 * 144; - break; - case '1w': - this.blocksInPeriod = 7 * 144; - break; case '1m': - this.blocksInPeriod = 30 * 144; + this.blocksInPeriod = 30.5 * 144; break; + case '1y': + this.blocksInPeriod = 30.5 * 144 * 365; + break; case 'all': this.blocksInPeriod = Infinity; break; diff --git a/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.html b/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.html index 9095a8129..1a8654432 100644 --- a/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.html +++ b/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.html @@ -26,12 +26,12 @@ @case ('24h') { (1 day) } - @case ('1w') { - (1 week) - } @case ('1m') { (1 month) } + @case ('1y') { + (1 year) + } @case ('all') { (all time) } @@ -45,12 +45,12 @@ 24h | - 1w - | 1m | + 1y + | all
@@ -79,13 +79,15 @@
-
Total Bid Boost
+
Historical Trend
diff --git a/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.ts b/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.ts index d84c6e97c..81cca468c 100644 --- a/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.ts +++ b/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.ts @@ -37,7 +37,7 @@ export class AcceleratorDashboardComponent implements OnInit, OnDestroy { webGlEnabled = true; seen: Set = new Set(); firstLoad = true; - timespan: '24h' | '3d' | '1w' | '1m' | 'all' = '1w'; + timespan: '24h' | '1m' | '1y' | 'all' = '1y'; accelerationDeltaSubscription: Subscription; From 6d749b71bcb05bc5ee75824a5a9207ad5860b01a Mon Sep 17 00:00:00 2001 From: natsoni Date: Mon, 17 Nov 2025 17:14:48 +0100 Subject: [PATCH 3/8] Prevent stacking of scheduled indexing runs --- backend/src/indexer.ts | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/backend/src/indexer.ts b/backend/src/indexer.ts index b3bfd2521..cdb4654ae 100644 --- a/backend/src/indexer.ts +++ b/backend/src/indexer.ts @@ -26,6 +26,7 @@ class Indexer { private indexerRunning = false; private tasksRunning: { [key in TaskName]?: boolean; } = {}; private tasksScheduled: { [key in TaskName]?: NodeJS.Timeout; } = {}; + private reindexTimeout: NodeJS.Timeout | undefined; private coreIndexes: CoreIndex[] = []; public indexerIsRunning(): boolean { @@ -76,10 +77,24 @@ class Indexer { public reindex(): void { if (Common.indexingEnabled()) { + if (this.reindexTimeout) { + clearTimeout(this.reindexTimeout); + this.reindexTimeout = undefined; + } this.runIndexer = true; } } + private scheduleNextRun(timeout: number): void { + if (this.reindexTimeout) { // Only one future run should be planned, so always replace existing timer + clearTimeout(this.reindexTimeout); + } + this.reindexTimeout = setTimeout(() => { + this.reindexTimeout = undefined; + this.reindex(); + }, timeout); + } + /** * schedules a single task to run in `timeout` ms * only one task of each type may be scheduled @@ -182,7 +197,7 @@ class Indexer { if (chainValid === false) { // Chain of block hash was invalid, so we need to reindex. Stop here and continue at the next iteration logger.warn(`The chain of block hash is invalid, re-indexing invalid data in 10 seconds.`, logger.tags.mining); - setTimeout(() => this.reindex(), 10000); + this.scheduleNextRun(10000); this.indexerRunning = false; return; } @@ -205,7 +220,7 @@ class Indexer { } catch (e) { this.indexerRunning = false; logger.err(`Indexer failed, trying again in 10 seconds. Reason: ` + (e instanceof Error ? e.message : e)); - setTimeout(() => this.reindex(), 10000); + this.scheduleNextRun(10000); this.indexerRunning = false; return; } @@ -214,7 +229,7 @@ class Indexer { const runEvery = 1000 * 3600; // 1 hour logger.debug(`Indexing completed. Next run planned at ${new Date(new Date().getTime() + runEvery).toUTCString()}`); - setTimeout(() => this.reindex(), runEvery); + this.scheduleNextRun(runEvery); } } From 1f3444aa1b372ca496cd67a813629230325f0049 Mon Sep 17 00:00:00 2001 From: natsoni <46578910+natsoni@users.noreply.github.com> Date: Thu, 27 Nov 2025 10:34:42 +0100 Subject: [PATCH 4/8] Don't schedule duplicate timeouts Co-authored-by: mononaut <83316221+mononaut@users.noreply.github.com> --- backend/src/indexer.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/backend/src/indexer.ts b/backend/src/indexer.ts index cdb4654ae..7e41aae23 100644 --- a/backend/src/indexer.ts +++ b/backend/src/indexer.ts @@ -86,13 +86,12 @@ class Indexer { } private scheduleNextRun(timeout: number): void { - if (this.reindexTimeout) { // Only one future run should be planned, so always replace existing timer - clearTimeout(this.reindexTimeout); + if (!this.reindexTimeout) { // Only one future run should be planned, ignore if already scheduled + this.reindexTimeout = setTimeout(() => { + this.reindexTimeout = undefined; + this.reindex(); + }, timeout); } - this.reindexTimeout = setTimeout(() => { - this.reindexTimeout = undefined; - this.reindex(); - }, timeout); } /** From 1f3ae67fb3a0f6ff5809e0094361a744ba303fc8 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Wed, 3 Dec 2025 02:01:11 +0000 Subject: [PATCH 5/8] fix recommended fee tests --- backend/src/api/fee-api.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/backend/src/api/fee-api.ts b/backend/src/api/fee-api.ts index 0914a1098..036acaa69 100644 --- a/backend/src/api/fee-api.ts +++ b/backend/src/api/fee-api.ts @@ -34,7 +34,11 @@ class FeeApi { const mPool = mempool.getMempoolInfo(); // minimum non-zero minrelaytxfee / incrementalrelayfee is 1 sat/kvB = 0.001 sat/vB - return this.calculateRecommendedFee(pBlocks, mPool, 0.001); + const recommendations = this.calculateRecommendedFee(pBlocks, mPool, 0.001); + // enforce floor & offset for highest priority recommendations while <100% hashrate accepts sub-sat fees + recommendations.fastestFee = Math.max(recommendations.fastestFee + this.priorityFactor, this.minFastestFee); + recommendations.halfHourFee = Math.max(recommendations.halfHourFee + (this.priorityFactor / 2), this.minHalfHourFee); + return recommendations; } public calculateRecommendedFee(pBlocks: MempoolBlock[], mPool: IBitcoinApi.MempoolInfo, minIncrement: number = this.minimumIncrement): RecommendedFees { @@ -70,8 +74,8 @@ class FeeApi { hourFee = Math.max(hourFee, economyFee); return { - 'fastestFee': Math.max(this.roundToNearest(fastestFee + this.priorityFactor, minIncrement), this.minFastestFee), - 'halfHourFee': Math.max(this.roundToNearest(halfHourFee + (this.priorityFactor / 2), minIncrement), this.minHalfHourFee), + 'fastestFee': this.roundToNearest(fastestFee, minIncrement), + 'halfHourFee': this.roundToNearest(halfHourFee, minIncrement), 'hourFee': this.roundToNearest(hourFee, minIncrement), 'economyFee': this.roundToNearest(economyFee, minIncrement), 'minimumFee': this.roundToNearest(minimumFee, minIncrement), From 3c9745be2f492ffb03649332871cc9dabd323152 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Wed, 3 Dec 2025 11:04:00 +0000 Subject: [PATCH 6/8] round precise fees to 3.d.p --- backend/src/api/fee-api.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/backend/src/api/fee-api.ts b/backend/src/api/fee-api.ts index 036acaa69..56106c7f5 100644 --- a/backend/src/api/fee-api.ts +++ b/backend/src/api/fee-api.ts @@ -38,7 +38,13 @@ class FeeApi { // enforce floor & offset for highest priority recommendations while <100% hashrate accepts sub-sat fees recommendations.fastestFee = Math.max(recommendations.fastestFee + this.priorityFactor, this.minFastestFee); recommendations.halfHourFee = Math.max(recommendations.halfHourFee + (this.priorityFactor / 2), this.minHalfHourFee); - return recommendations; + return { + 'fastestFee': Math.round(recommendations.fastestFee * 1000) / 1000, + 'halfHourFee': Math.round(recommendations.halfHourFee * 1000) / 1000, + 'hourFee': Math.round(recommendations.hourFee * 1000) / 1000, + 'economyFee': Math.round(recommendations.economyFee * 1000) / 1000, + 'minimumFee': Math.round(recommendations.minimumFee * 1000) / 1000, + }; } public calculateRecommendedFee(pBlocks: MempoolBlock[], mPool: IBitcoinApi.MempoolInfo, minIncrement: number = this.minimumIncrement): RecommendedFees { From 56953c5221fd5eb93104f158b8df2d662ffc9494 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Fri, 5 Dec 2025 05:28:55 +0000 Subject: [PATCH 7/8] set indexer flags earlier --- backend/src/indexer.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/indexer.ts b/backend/src/indexer.ts index 7e41aae23..b733a6e2c 100644 --- a/backend/src/indexer.ts +++ b/backend/src/indexer.ts @@ -170,6 +170,9 @@ class Indexer { return; } + this.runIndexer = false; + this.indexerRunning = true; + if (config.FIAT_PRICE.ENABLED) { try { await priceUpdater.$run(); @@ -184,9 +187,6 @@ class Indexer { return; } - this.runIndexer = false; - this.indexerRunning = true; - logger.debug(`Running mining indexer`); await this.checkAvailableCoreIndexes(); From bf76678eefcaf9eda976562ee1dedd14d3e8f339 Mon Sep 17 00:00:00 2001 From: natsoni Date: Fri, 5 Dec 2025 16:46:38 +0100 Subject: [PATCH 8/8] Fix indexer retry flow --- backend/src/indexer.ts | 63 +++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/backend/src/indexer.ts b/backend/src/indexer.ts index b733a6e2c..ca0b2303c 100644 --- a/backend/src/indexer.ts +++ b/backend/src/indexer.ts @@ -173,31 +173,37 @@ class Indexer { this.runIndexer = false; this.indexerRunning = true; - if (config.FIAT_PRICE.ENABLED) { - try { - await priceUpdater.$run(); - } catch (e) { - logger.err(`Running priceUpdater failed. Reason: ` + (e instanceof Error ? e.message : e)); - } - } - - // Do not attempt to index anything unless Bitcoin Core is fully synced - const blockchainInfo = await bitcoinClient.getBlockchainInfo(); - if (blockchainInfo.blocks !== blockchainInfo.headers) { - return; - } - - logger.debug(`Running mining indexer`); - - await this.checkAvailableCoreIndexes(); + const retryDelay = 10000; + const runEvery = 1000 * 3600; // 1 hour + let nextRunDelay = runEvery; + let runSuccessful = false; try { + if (config.FIAT_PRICE.ENABLED) { + try { + await priceUpdater.$run(); + } catch (e) { + logger.err(`Running priceUpdater failed. Reason: ` + (e instanceof Error ? e.message : e)); + } + } + + // Do not attempt to index anything unless Bitcoin Core is fully synced + const blockchainInfo = await bitcoinClient.getBlockchainInfo(); + if (blockchainInfo.blocks !== blockchainInfo.headers) { + logger.debug(`Bitcoin Core not fully synced, retrying index run in 10 seconds.`); + nextRunDelay = retryDelay; + return; + } + + logger.debug(`Running mining indexer`); + + await this.checkAvailableCoreIndexes(); + const chainValid = await blocks.$generateBlockDatabase(); if (chainValid === false) { // Chain of block hash was invalid, so we need to reindex. Stop here and continue at the next iteration logger.warn(`The chain of block hash is invalid, re-indexing invalid data in 10 seconds.`, logger.tags.mining); - this.scheduleNextRun(10000); - this.indexerRunning = false; + nextRunDelay = retryDelay; return; } @@ -216,19 +222,20 @@ class Indexer { await BlocksRepository.$migrateBlocks(); // do not wait for classify blocks to finish blocks.$classifyBlocks(); + runSuccessful = true; } catch (e) { - this.indexerRunning = false; + nextRunDelay = retryDelay; logger.err(`Indexer failed, trying again in 10 seconds. Reason: ` + (e instanceof Error ? e.message : e)); - this.scheduleNextRun(10000); + } finally { this.indexerRunning = false; - return; + const nextRunAt = new Date(Date.now() + nextRunDelay).toUTCString(); + if (runSuccessful) { + logger.debug(`Indexing completed. Next run planned at ${nextRunAt}`); + } else { + logger.debug(`Indexing did not complete, next run planned at ${nextRunAt}`); + } + this.scheduleNextRun(nextRunDelay); } - - this.indexerRunning = false; - - const runEvery = 1000 * 3600; // 1 hour - logger.debug(`Indexing completed. Next run planned at ${new Date(new Date().getTime() + runEvery).toUTCString()}`); - this.scheduleNextRun(runEvery); } }