warn on re-index - fix hash indexing state issue - cleanup ui mining

This commit is contained in:
nymkappa 2022-02-24 20:20:18 +09:00
parent 54ccfe070e
commit ec40231f93
No known key found for this signature in database
GPG Key ID: E155910B16E8BD04
11 changed files with 45 additions and 53 deletions

View File

@ -92,11 +92,13 @@ class DatabaseMigration {
await this.$executeQuery(connection, this.getCreateBlocksTableQuery(), await this.$checkIfTableExists('blocks')); await this.$executeQuery(connection, this.getCreateBlocksTableQuery(), await this.$checkIfTableExists('blocks'));
} }
if (databaseSchemaVersion < 5 && isBitcoin === true) { if (databaseSchemaVersion < 5 && isBitcoin === true) {
logger.warn(`'blocks' table has been truncated. Re-indexing from scratch.'`);
await this.$executeQuery(connection, 'TRUNCATE blocks;'); // Need to re-index await this.$executeQuery(connection, 'TRUNCATE blocks;'); // Need to re-index
await this.$executeQuery(connection, 'ALTER TABLE blocks ADD `reward` double unsigned NOT NULL DEFAULT "0"'); await this.$executeQuery(connection, 'ALTER TABLE blocks ADD `reward` double unsigned NOT NULL DEFAULT "0"');
} }
if (databaseSchemaVersion < 6 && isBitcoin === true) { if (databaseSchemaVersion < 6 && isBitcoin === true) {
logger.warn(`'blocks' table has been truncated. Re-indexing from scratch.'`);
await this.$executeQuery(connection, 'TRUNCATE blocks;'); // Need to re-index await this.$executeQuery(connection, 'TRUNCATE blocks;'); // Need to re-index
// Cleanup original blocks fields type // Cleanup original blocks fields type
await this.$executeQuery(connection, 'ALTER TABLE blocks MODIFY `height` integer unsigned NOT NULL DEFAULT "0"'); await this.$executeQuery(connection, 'ALTER TABLE blocks MODIFY `height` integer unsigned NOT NULL DEFAULT "0"');
@ -123,7 +125,8 @@ class DatabaseMigration {
} }
if (databaseSchemaVersion < 8 && isBitcoin === true) { if (databaseSchemaVersion < 8 && isBitcoin === true) {
await this.$executeQuery(connection, 'TRUNCATE hashrates;'); logger.warn(`'hashrates' table has been truncated. Re-indexing from scratch.'`);
await this.$executeQuery(connection, 'TRUNCATE hashrates;'); // Need to re-index
await this.$executeQuery(connection, 'ALTER TABLE `hashrates` DROP INDEX `PRIMARY`'); await this.$executeQuery(connection, 'ALTER TABLE `hashrates` DROP INDEX `PRIMARY`');
await this.$executeQuery(connection, 'ALTER TABLE `hashrates` ADD `id` int NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST'); await this.$executeQuery(connection, 'ALTER TABLE `hashrates` ADD `id` int NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST');
await this.$executeQuery(connection, 'ALTER TABLE `hashrates` ADD `share` float NOT NULL DEFAULT "0"'); await this.$executeQuery(connection, 'ALTER TABLE `hashrates` ADD `share` float NOT NULL DEFAULT "0"');

View File

@ -27,6 +27,7 @@ import syncAssets from './sync-assets';
import icons from './api/liquid/icons'; import icons from './api/liquid/icons';
import { Common } from './api/common'; import { Common } from './api/common';
import mining from './api/mining'; import mining from './api/mining';
import HashratesRepository from './repositories/HashratesRepository';
class Server { class Server {
private wss: WebSocket.Server | undefined; private wss: WebSocket.Server | undefined;
@ -95,6 +96,7 @@ class Server {
await Common.sleep(5000); await Common.sleep(5000);
await databaseMigration.$truncateIndexedData(tables); await databaseMigration.$truncateIndexedData(tables);
} }
await this.$resetHashratesIndexingState();
await databaseMigration.$initializeOrMigrateDatabase(); await databaseMigration.$initializeOrMigrateDatabase();
await poolsParser.migratePoolsJson(); await poolsParser.migratePoolsJson();
} catch (e) { } catch (e) {
@ -145,7 +147,7 @@ class Server {
} }
await blocks.$updateBlocks(); await blocks.$updateBlocks();
await memPool.$updateMempool(); await memPool.$updateMempool();
this.runIndexingWhenReady(); this.$runIndexingWhenReady();
setTimeout(this.runMainUpdateLoop.bind(this), config.MEMPOOL.POLL_RATE_MS); setTimeout(this.runMainUpdateLoop.bind(this), config.MEMPOOL.POLL_RATE_MS);
this.currentBackendRetryInterval = 5; this.currentBackendRetryInterval = 5;
@ -164,7 +166,11 @@ class Server {
} }
} }
async runIndexingWhenReady() { async $resetHashratesIndexingState() {
return await HashratesRepository.$setLatestRunTimestamp(0);
}
async $runIndexingWhenReady() {
if (!Common.indexingEnabled() || mempool.hasPriority()) { if (!Common.indexingEnabled() || mempool.hasPriority()) {
return; return;
} }

View File

@ -84,10 +84,11 @@ class HashratesRepository {
return rows; return rows;
} }
public async $setLatestRunTimestamp() { public async $setLatestRunTimestamp(val: any = null) {
const connection = await DB.pool.getConnection(); const connection = await DB.pool.getConnection();
const query = `UPDATE state SET number = ? WHERE name = 'last_hashrates_indexing'`; const query = `UPDATE state SET number = ? WHERE name = 'last_hashrates_indexing'`;
await connection.query<any>(query, [Math.round(new Date().getTime() / 1000)]);
await connection.query<any>(query, (val === null) ? [Math.round(new Date().getTime() / 1000)] : [val]);
connection.release(); connection.release();
} }

View File

@ -45,12 +45,15 @@ export class HashrateChartComponent implements OnInit {
private apiService: ApiService, private apiService: ApiService,
private formBuilder: FormBuilder, private formBuilder: FormBuilder,
) { ) {
this.seoService.setTitle($localize`:@@mining.hashrate-difficulty:Hashrate and Difficulty`);
this.radioGroupForm = this.formBuilder.group({ dateSpan: '1y' }); this.radioGroupForm = this.formBuilder.group({ dateSpan: '1y' });
this.radioGroupForm.controls.dateSpan.setValue('1y'); this.radioGroupForm.controls.dateSpan.setValue('1y');
} }
ngOnInit(): void { ngOnInit(): void {
if (!this.widget) {
this.seoService.setTitle($localize`:@@mining.hashrate-difficulty:Hashrate and Difficulty`);
}
this.hashrateObservable$ = this.radioGroupForm.get('dateSpan').valueChanges this.hashrateObservable$ = this.radioGroupForm.get('dateSpan').valueChanges
.pipe( .pipe(
startWith('1y'), startWith('1y'),

View File

@ -30,29 +30,5 @@
<div class="text-center loadingGraphs" *ngIf="isLoading"> <div class="text-center loadingGraphs" *ngIf="isLoading">
<div class="spinner-border text-light"></div> <div class="spinner-border text-light"></div>
</div> </div>
<!-- <div class="mt-3" *ngIf="!widget">
<table class="table table-borderless table-sm text-center">
<thead>
<tr>
<th i18n="mining.rank">Block</th>
<th class="d-none d-md-block" i18n="block.timestamp">Timestamp</th>
<th i18n="mining.adjusted">Adjusted</th>
<th i18n="mining.difficulty">Difficulty</th>
<th i18n="mining.change">Change</th>
</tr>
</thead>
<tbody *ngIf="(hashrateObservable$ | async) as data">
<tr *ngFor="let diffChange of data.difficulty">
<td><a [routerLink]="['/block' | relativeUrl, diffChange.height]">{{ diffChange.height }}</a></td>
<td class="d-none d-md-block">&lrm;{{ diffChange.timestamp * 1000 | date:'yyyy-MM-dd HH:mm' }}</td>
<td><app-time-since [time]="diffChange.timestamp" [fastRender]="true"></app-time-since></td>
<td class="d-none d-md-block">{{ formatNumber(diffChange.difficulty, locale, '1.2-2') }}</td>
<td class="d-block d-md-none">{{ diffChange.difficultyShorten }}</td>
<td [style]="diffChange.change >= 0 ? 'color: #42B747' : 'color: #B74242'">{{ formatNumber(diffChange.change, locale, '1.2-2') }}%</td>
</tr>
</tbody>
</table>
</div> -->
</div> </div>

View File

@ -11,12 +11,12 @@
.full-container { .full-container {
width: 100%; width: 100%;
height: calc(100% - 50px); height: calc(100% - 100px);
@media (max-width: 992px) { @media (max-width: 992px) {
height: calc(100% - 110px); height: calc(100% - 140px);
}; };
@media (max-width: 576px) { @media (max-width: 576px) {
height: calc(100% - 130px); height: calc(100% - 180px);
}; };
} }

View File

@ -1,10 +1,9 @@
import { Component, Inject, Input, LOCALE_ID, OnInit } from '@angular/core'; import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit } from '@angular/core';
import { EChartsOption } from 'echarts'; import { EChartsOption } from 'echarts';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { map, share, startWith, switchMap, tap } from 'rxjs/operators'; import { map, share, startWith, switchMap, tap } from 'rxjs/operators';
import { ApiService } from 'src/app/services/api.service'; import { ApiService } from 'src/app/services/api.service';
import { SeoService } from 'src/app/services/seo.service'; import { SeoService } from 'src/app/services/seo.service';
import { formatNumber } from '@angular/common';
import { FormBuilder, FormGroup } from '@angular/forms'; import { FormBuilder, FormGroup } from '@angular/forms';
import { poolsColor } from 'src/app/app.constants'; import { poolsColor } from 'src/app/app.constants';
@ -15,11 +14,12 @@ import { poolsColor } from 'src/app/app.constants';
styles: [` styles: [`
.loadingGraphs { .loadingGraphs {
position: absolute; position: absolute;
top: 38%; top: 50%;
left: calc(50% - 15px); left: calc(50% - 15px);
z-index: 100; z-index: 100;
} }
`], `],
changeDetection: ChangeDetectionStrategy.OnPush,
}) })
export class HashrateChartPoolsComponent implements OnInit { export class HashrateChartPoolsComponent implements OnInit {
@Input() widget: boolean = false; @Input() widget: boolean = false;
@ -37,7 +37,6 @@ export class HashrateChartPoolsComponent implements OnInit {
hashrateObservable$: Observable<any>; hashrateObservable$: Observable<any>;
isLoading = true; isLoading = true;
formatNumber = formatNumber;
constructor( constructor(
@Inject(LOCALE_ID) public locale: string, @Inject(LOCALE_ID) public locale: string,
@ -45,19 +44,24 @@ export class HashrateChartPoolsComponent implements OnInit {
private apiService: ApiService, private apiService: ApiService,
private formBuilder: FormBuilder, private formBuilder: FormBuilder,
) { ) {
this.seoService.setTitle($localize`:@@mining.hashrate-difficulty:Hashrate and Difficulty`);
this.radioGroupForm = this.formBuilder.group({ dateSpan: '1y' }); this.radioGroupForm = this.formBuilder.group({ dateSpan: '1y' });
this.radioGroupForm.controls.dateSpan.setValue('1y'); this.radioGroupForm.controls.dateSpan.setValue('1y');
} }
ngOnInit(): void { ngOnInit(): void {
if (!this.widget) {
this.seoService.setTitle($localize`:@@mining.pools-historical-dominance:Pools Historical Dominance`);
}
this.hashrateObservable$ = this.radioGroupForm.get('dateSpan').valueChanges this.hashrateObservable$ = this.radioGroupForm.get('dateSpan').valueChanges
.pipe( .pipe(
startWith('1y'), startWith('1y'),
switchMap((timespan) => { switchMap((timespan) => {
this.isLoading = true;
return this.apiService.getHistoricalPoolsHashrate$(timespan) return this.apiService.getHistoricalPoolsHashrate$(timespan)
.pipe( .pipe(
tap((data: any) => { tap((data: any) => {
// Prepare series (group all hashrates data point by pool)
const grouped = {}; const grouped = {};
for (const hashrate of data.hashrates) { for (const hashrate of data.hashrates) {
if (!grouped.hasOwnProperty(hashrate.poolName)) { if (!grouped.hasOwnProperty(hashrate.poolName)) {
@ -68,7 +72,6 @@ export class HashrateChartPoolsComponent implements OnInit {
const series = []; const series = [];
const legends = []; const legends = [];
for (const name in grouped) { for (const name in grouped) {
series.push({ series.push({
stack: 'Total', stack: 'Total',
@ -76,12 +79,8 @@ export class HashrateChartPoolsComponent implements OnInit {
showSymbol: false, showSymbol: false,
data: grouped[name].map((val) => [val.timestamp * 1000, (val.share * 100).toFixed(2)]), data: grouped[name].map((val) => [val.timestamp * 1000, (val.share * 100).toFixed(2)]),
type: 'line', type: 'line',
lineStyle: { lineStyle: { width: 0 },
width: 0, areaStyle: { opacity: 1 },
},
areaStyle: {
opacity: 1,
},
smooth: true, smooth: true,
color: poolsColor[name.replace(/[^a-zA-Z0-9]/g, "").toLowerCase()], color: poolsColor[name.replace(/[^a-zA-Z0-9]/g, "").toLowerCase()],
emphasis: { emphasis: {
@ -115,7 +114,6 @@ export class HashrateChartPoolsComponent implements OnInit {
) / 3600 / 24; ) / 3600 / 24;
return { return {
availableTimespanDay: availableTimespanDay, availableTimespanDay: availableTimespanDay,
hashrates: data
}; };
}), }),
); );
@ -129,7 +127,7 @@ export class HashrateChartPoolsComponent implements OnInit {
grid: { grid: {
right: this.right, right: this.right,
left: this.left, left: this.left,
bottom: this.widget ? 30 : 60, bottom: this.widget ? 30 : 20,
top: this.widget ? 10 : 40, top: this.widget ? 10 : 40,
}, },
tooltip: { tooltip: {

View File

@ -8,7 +8,7 @@
<div class="card-body"> <div class="card-body">
<h5 class="card-title"> <h5 class="card-title">
<a class="link" href="" [routerLink]="['/mining/hashrate/pools' | relativeUrl]" i18n="mining.pools-hashrate"> <a class="link" href="" [routerLink]="['/mining/hashrate/pools' | relativeUrl]" i18n="mining.pools-hashrate">
Pools Hashrate Share (1y) Mining Pools Dominance (1y)
</a> </a>
</h5> </h5>
<app-hashrate-chart-pools [widget]=true></app-hashrate-chart-pools> <app-hashrate-chart-pools [widget]=true></app-hashrate-chart-pools>

View File

@ -12,7 +12,7 @@
.card { .card {
background-color: #1d1f31; background-color: #1d1f31;
height: 100%; height: 340px;
} }
.card-title { .card-title {

View File

@ -1,4 +1,5 @@
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { SeoService } from 'src/app/services/seo.service';
@Component({ @Component({
selector: 'app-mining-dashboard', selector: 'app-mining-dashboard',
@ -8,7 +9,9 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
}) })
export class MiningDashboardComponent implements OnInit { export class MiningDashboardComponent implements OnInit {
constructor() { } constructor(private seoService: SeoService) {
this.seoService.setTitle($localize`:@@mining.mining-dashboard:Mining Dashboard`);
}
ngOnInit(): void { ngOnInit(): void {
} }

View File

@ -1,4 +1,4 @@
import { Component, Input, OnInit } from '@angular/core'; import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms'; import { FormBuilder, FormGroup } from '@angular/forms';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { EChartsOption, PieSeriesOption } from 'echarts'; import { EChartsOption, PieSeriesOption } from 'echarts';
@ -18,11 +18,12 @@ import { chartColors, poolsColor } from 'src/app/app.constants';
styles: [` styles: [`
.loadingGraphs { .loadingGraphs {
position: absolute; position: absolute;
top: 38%; top: 50%;
left: calc(50% - 15px); left: calc(50% - 15px);
z-index: 100; z-index: 100;
} }
`], `],
changeDetection: ChangeDetectionStrategy.OnPush,
}) })
export class PoolRankingComponent implements OnInit { export class PoolRankingComponent implements OnInit {
@Input() widget: boolean = false; @Input() widget: boolean = false;
@ -49,13 +50,13 @@ export class PoolRankingComponent implements OnInit {
private seoService: SeoService, private seoService: SeoService,
private router: Router, private router: Router,
) { ) {
this.seoService.setTitle($localize`:@@mining.mining-pools:Mining Pools`);
} }
ngOnInit(): void { ngOnInit(): void {
if (this.widget) { if (this.widget) {
this.poolsWindowPreference = '1w'; this.poolsWindowPreference = '1w';
} else { } else {
this.seoService.setTitle($localize`:@@mining.mining-pools:Mining Pools`);
this.poolsWindowPreference = this.storageService.getValue('poolsWindowPreference') ? this.storageService.getValue('poolsWindowPreference') : '1w'; this.poolsWindowPreference = this.storageService.getValue('poolsWindowPreference') ? this.storageService.getValue('poolsWindowPreference') : '1w';
} }
this.radioGroupForm = this.formBuilder.group({ dateSpan: this.poolsWindowPreference }); this.radioGroupForm = this.formBuilder.group({ dateSpan: this.poolsWindowPreference });
@ -167,6 +168,7 @@ export class PoolRankingComponent implements OnInit {
} }
this.chartOptions = { this.chartOptions = {
color: chartColors,
title: { title: {
text: this.widget ? '' : $localize`:@@mining.pool-chart-title:${network}:NETWORK: mining pools share`, text: this.widget ? '' : $localize`:@@mining.pool-chart-title:${network}:NETWORK: mining pools share`,
left: 'center', left: 'center',