[nodejs backend] added /api/v1/health

This commit is contained in:
nymkappa 2023-09-26 16:36:29 +02:00
parent 5e95d8d6ce
commit 8a51f32e63
No known key found for this signature in database
GPG Key ID: E155910B16E8BD04
2 changed files with 104 additions and 7 deletions

View File

@ -6,7 +6,7 @@ import websocketHandler from '../websocket-handler';
import mempool from '../mempool'; import mempool from '../mempool';
import feeApi from '../fee-api'; import feeApi from '../fee-api';
import mempoolBlocks from '../mempool-blocks'; import mempoolBlocks from '../mempool-blocks';
import bitcoinApi from './bitcoin-api-factory'; import bitcoinApi, { bitcoinCoreApi } from './bitcoin-api-factory';
import { Common } from '../common'; import { Common } from '../common';
import backendInfo from '../backend-info'; import backendInfo from '../backend-info';
import transactionUtils from '../transaction-utils'; import transactionUtils from '../transaction-utils';
@ -19,6 +19,7 @@ import bitcoinClient from './bitcoin-client';
import difficultyAdjustment from '../difficulty-adjustment'; import difficultyAdjustment from '../difficulty-adjustment';
import transactionRepository from '../../repositories/TransactionRepository'; import transactionRepository from '../../repositories/TransactionRepository';
import rbfCache from '../rbf-cache'; import rbfCache from '../rbf-cache';
import BlocksRepository from '../../repositories/BlocksRepository';
class BitcoinRoutes { class BitcoinRoutes {
public initRoutes(app: Application) { public initRoutes(app: Application) {
@ -126,8 +127,53 @@ class BitcoinRoutes {
.get(config.MEMPOOL.API_URL_PREFIX + 'address-prefix/:prefix', this.getAddressPrefix) .get(config.MEMPOOL.API_URL_PREFIX + 'address-prefix/:prefix', this.getAddressPrefix)
; ;
} }
app.get(config.MEMPOOL.API_URL_PREFIX + 'health', this.generateHealthReport)
} }
private async generateHealthReport(req: Request, res: Response) {
try {
// Bitcoin Core
const bitcoinCoreBlockHeight = await bitcoinCoreApi.$getBlockHeightTip();
const bitcoinCoreIndexes = await bitcoinClient.getIndexInfo();
// Esplora
const esploraBlockHeight = await bitcoinApi.$getBlockHeightTip();
// Mempool
const mempoolBlockHeight = blocks.getCurrentBlockHeight();
const indexedBlockCount = await BlocksRepository.$getIndexedBlockCount();
const indexedBlockWithCpfpCount = await BlocksRepository.$getIndexedCpfpBlockCount();
const indexedBlockWithCoinStatsCount = await BlocksRepository.$getIndexedCoinStatsBlockCount();
const response = {
core: {
height: bitcoinCoreBlockHeight,
},
esplora: {
height: esploraBlockHeight
},
mempool: {
height: mempoolBlockHeight,
indexing: {
indexedBlockCount: indexedBlockCount,
indexedBlockCountWithCPFP: indexedBlockWithCpfpCount,
indexedBlockCountWithCoinStats: indexedBlockWithCoinStatsCount,
}
}
};
// Bitcoin Core indexes
for (const indexName in bitcoinCoreIndexes) {
response.core[indexName] = bitcoinCoreIndexes[indexName];
}
res.json(response);
} catch (e: any) {
logger.err(`Unable to generate health report. Exception: ${JSON.stringify(e)}`);
logger.err(e.stack);
res.status(500).send(e instanceof Error ? e.message : e);
}
}
private getInitData(req: Request, res: Response) { private getInitData(req: Request, res: Response) {
try { try {

View File

@ -1061,6 +1061,57 @@ class BlocksRepository {
blk.extras = <BlockExtension>extras; blk.extras = <BlockExtension>extras;
return <BlockExtended>blk; return <BlockExtended>blk;
} }
/**
* Count how many blocks are indexed
*/
public async $getIndexedBlockCount(): Promise<number> {
try {
const [res]: any[] = await DB.query(`SELECT COUNT(hash) as count FROM blocks`);
if (!res || !res.length) {
logger.err(`Unable to count indexed blocks in our db`);
return -1;
}
return res[0].count;
} catch (e) {
logger.err(`Unable to count indexed blocks in our db. Exception: ${JSON.stringify(e)}`);
return -1;
}
}
/**
* Count how many blocks are indexed with CPFP data
*/
public async $getIndexedCpfpBlockCount(): Promise<number> {
try {
const [res]: any[] = await DB.query(`SELECT COUNT(DISTINCT height) as count FROM compact_cpfp_clusters`);
if (!res || !res.length) {
logger.err(`Unable to count indexed blocks with CPFP data in our db`);
return -1;
}
return res[0].count;
} catch (e) {
logger.err(`Unable to count indexed blocks with CPFP data in our db. Exception: ${JSON.stringify(e)}`);
return -1;
}
}
/**
* Count how many blocks are indexed with coin stats data
*/
public async $getIndexedCoinStatsBlockCount(): Promise<number> {
try {
const [res]: any[] = await DB.query(`SELECT COUNT(hash) as count FROM blocks WHERE utxoset_size IS NOT NULL && total_input_amt IS NOT NULL`);
if (!res || !res.length) {
logger.err(`Unable to count indexed blocks with coin stats data in our db`);
return -1;
}
return res[0].count;
} catch (e) {
logger.err(`Unable to count indexed blocks with coin stats data in our db. Exception: ${JSON.stringify(e)}`);
return -1;
}
}
} }
export default new BlocksRepository(); export default new BlocksRepository();