2022-05-19 16:40:38 +02:00
|
|
|
import { Common } from './api/common';
|
|
|
|
import blocks from './api/blocks';
|
|
|
|
import mempool from './api/mempool';
|
2022-07-11 19:15:28 +02:00
|
|
|
import mining from './api/mining/mining';
|
2022-05-19 16:40:38 +02:00
|
|
|
import logger from './logger';
|
|
|
|
import HashratesRepository from './repositories/HashratesRepository';
|
2022-06-14 10:58:17 +02:00
|
|
|
import bitcoinClient from './api/bitcoin/bitcoin-client';
|
2022-07-11 23:16:48 +02:00
|
|
|
import priceUpdater from './tasks/price-updater';
|
2022-07-16 09:22:45 +02:00
|
|
|
import PricesRepository from './repositories/PricesRepository';
|
2022-05-19 16:40:38 +02:00
|
|
|
|
|
|
|
class Indexer {
|
|
|
|
runIndexer = true;
|
|
|
|
indexerRunning = false;
|
2022-07-16 09:22:45 +02:00
|
|
|
tasksRunning: string[] = [];
|
2022-05-19 16:40:38 +02:00
|
|
|
|
|
|
|
public reindex() {
|
2022-06-07 11:28:39 +02:00
|
|
|
if (Common.indexingEnabled()) {
|
|
|
|
this.runIndexer = true;
|
|
|
|
}
|
2022-05-19 16:40:38 +02:00
|
|
|
}
|
|
|
|
|
2022-07-16 09:22:45 +02:00
|
|
|
public async runSingleTask(task: 'blocksPrices') {
|
|
|
|
if (!Common.indexingEnabled()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (task === 'blocksPrices' && !this.tasksRunning.includes(task)) {
|
|
|
|
this.tasksRunning.push(task);
|
|
|
|
const lastestPriceId = await PricesRepository.$getLatestPriceId();
|
|
|
|
if (priceUpdater.historyInserted === false || lastestPriceId === null) {
|
|
|
|
logger.debug(`Blocks prices indexer is waiting for the price updater to complete`)
|
|
|
|
setTimeout(() => {
|
|
|
|
this.tasksRunning = this.tasksRunning.filter(runningTask => runningTask != task)
|
|
|
|
this.runSingleTask('blocksPrices');
|
|
|
|
}, 10000);
|
|
|
|
} else {
|
|
|
|
logger.debug(`Blocks prices indexer will run now`)
|
|
|
|
await mining.$indexBlockPrices();
|
|
|
|
this.tasksRunning = this.tasksRunning.filter(runningTask => runningTask != task)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-19 16:40:38 +02:00
|
|
|
public async $run() {
|
|
|
|
if (!Common.indexingEnabled() || this.runIndexer === false ||
|
|
|
|
this.indexerRunning === true || mempool.hasPriority()
|
|
|
|
) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-06-14 10:58:17 +02:00
|
|
|
// Do not attempt to index anything unless Bitcoin Core is fully synced
|
|
|
|
const blockchainInfo = await bitcoinClient.getBlockchainInfo();
|
|
|
|
if (blockchainInfo.blocks !== blockchainInfo.headers) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-05-19 16:40:38 +02:00
|
|
|
this.runIndexer = false;
|
|
|
|
this.indexerRunning = true;
|
|
|
|
|
2022-07-09 18:25:16 +02:00
|
|
|
logger.debug(`Running mining indexer`);
|
|
|
|
|
2022-05-19 16:40:38 +02:00
|
|
|
try {
|
2022-07-11 23:16:48 +02:00
|
|
|
await priceUpdater.$run();
|
|
|
|
|
2022-06-20 16:35:10 +02:00
|
|
|
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
|
2022-06-25 19:50:39 +02:00
|
|
|
logger.warn(`The chain of block hash is invalid, re-indexing invalid data in 10 seconds.`);
|
|
|
|
setTimeout(() => this.reindex(), 10000);
|
2022-06-20 16:35:10 +02:00
|
|
|
this.indexerRunning = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-07-16 09:22:45 +02:00
|
|
|
this.runSingleTask('blocksPrices');
|
2022-06-25 12:14:32 +02:00
|
|
|
await mining.$indexDifficultyAdjustments();
|
2022-07-09 16:53:29 +02:00
|
|
|
await this.$resetHashratesIndexingState(); // TODO - Remove this as it's not efficient
|
2022-05-19 16:40:38 +02:00
|
|
|
await mining.$generateNetworkHashrateHistory();
|
|
|
|
await mining.$generatePoolHashrateHistory();
|
2022-06-18 16:48:02 +02:00
|
|
|
await blocks.$generateBlocksSummariesDatabase();
|
2022-11-27 13:46:23 +09:00
|
|
|
await blocks.$generateCPFPDatabase();
|
2022-05-19 16:40:38 +02:00
|
|
|
} catch (e) {
|
2022-06-25 19:50:39 +02:00
|
|
|
this.indexerRunning = false;
|
|
|
|
logger.err(`Indexer failed, trying again in 10 seconds. Reason: ` + (e instanceof Error ? e.message : e));
|
|
|
|
setTimeout(() => this.reindex(), 10000);
|
2022-07-09 18:25:16 +02:00
|
|
|
this.indexerRunning = false;
|
|
|
|
return;
|
2022-05-19 16:40:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
this.indexerRunning = false;
|
2022-07-09 18:25:16 +02:00
|
|
|
|
|
|
|
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);
|
2022-05-19 16:40:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
async $resetHashratesIndexingState() {
|
|
|
|
try {
|
|
|
|
await HashratesRepository.$setLatestRun('last_hashrates_indexing', 0);
|
|
|
|
await HashratesRepository.$setLatestRun('last_weekly_hashrates_indexing', 0);
|
|
|
|
} catch (e) {
|
|
|
|
logger.err(`Cannot reset hashrate indexing timestamps. Reason: ` + (e instanceof Error ? e.message : e));
|
2022-06-25 19:50:39 +02:00
|
|
|
throw e;
|
2022-05-19 16:40:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export default new Indexer();
|