Merge pull request #6628 from mempool/mononaut/optimize-pool-stats

optimize mining endpoints
This commit is contained in:
wiz 2026-07-14 16:30:54 +09:00 committed by GitHub
commit c9f64aec4f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 26 additions and 49 deletions

View file

@ -114,31 +114,29 @@ class Mining {
const poolsStatistics = {};
const poolsInfo: PoolInfo[] = await PoolsRepository.$getPoolsInfo(interval);
const emptyBlocks: any[] = await BlocksRepository.$countEmptyBlocks(null, interval);
const poolsStats: PoolStats[] = [];
let rank = 1;
let blockCount = 0;
poolsInfo.forEach((poolInfo: PoolInfo) => {
const emptyBlocksCount = emptyBlocks.filter((emptyCount) => emptyCount.poolId === poolInfo.poolId);
const poolStat: PoolStats = {
poolId: poolInfo.poolId, // mysql row id
name: poolInfo.name,
link: poolInfo.link,
blockCount: poolInfo.blockCount,
rank: rank++,
emptyBlocks: emptyBlocksCount.length > 0 ? emptyBlocksCount[0]['count'] : 0,
emptyBlocks: poolInfo.emptyBlocks,
slug: poolInfo.slug,
avgMatchRate: poolInfo.avgMatchRate !== null ? Math.round(100 * poolInfo.avgMatchRate) / 100 : null,
avgFeeDelta: poolInfo.avgFeeDelta,
poolUniqueId: poolInfo.poolUniqueId
};
poolsStats.push(poolStat);
blockCount += poolInfo.blockCount;
});
poolsStatistics['pools'] = poolsStats;
const blockCount: number = await BlocksRepository.$blockCount(null, interval);
poolsStatistics['blockCount'] = blockCount;
const totalBlock24h: number = await BlocksRepository.$blockCount(null, '24h');
@ -151,6 +149,8 @@ class Mining {
poolsStatistics['lastEstimatedHashrate1w'] = await bitcoinClient.getNetworkHashPs(totalBlock1w);
} catch (e) {
poolsStatistics['lastEstimatedHashrate'] = 0;
poolsStatistics['lastEstimatedHashrate3d'] = 0;
poolsStatistics['lastEstimatedHashrate1w'] = 0;
logger.debug('Bitcoin Core is not available, using zeroed value for current hashrate', logger.tags.mining);
}

View file

@ -17,6 +17,7 @@ export interface PoolInfo {
name: string;
link: string;
blockCount: number;
emptyBlocks: number;
slug: string;
avgMatchRate: number | null;
avgFeeDelta: number | null;
@ -25,7 +26,6 @@ export interface PoolInfo {
export interface PoolStats extends PoolInfo {
rank: number;
emptyBlocks: number;
}
export enum TemplateAlgorithm {

View file

@ -305,39 +305,6 @@ class BlocksRepository {
}
}
/**
* Get empty blocks for one or all pools
* @asyncSafe
*/
public async $countEmptyBlocks(poolId: number | null, interval: string | null = null): Promise<any> {
interval = Common.getSqlInterval(interval);
const params: any[] = [];
let query = `SELECT count(height) as count, pools.id as poolId
FROM blocks
JOIN pools on pools.id = blocks.pool_id
WHERE tx_count = 1 AND stale = 0`;
if (poolId) {
query += ` AND pool_id = ?`;
params.push(poolId);
}
if (interval) {
query += ` AND blockTimestamp BETWEEN DATE_SUB(NOW(), INTERVAL ${interval}) AND NOW()`;
}
query += ` GROUP by pools.id`;
try {
const [rows] = await DB.query(query, params);
return rows;
} catch (e) {
logger.err('Cannot count empty blocks. Reason: ' + (e instanceof Error ? e.message : e));
throw e;
}
}
/**
* Return most recent block height
* @asyncSafe
@ -360,17 +327,26 @@ class BlocksRepository {
interval = Common.getSqlInterval(interval);
const params: any[] = [];
let query = `SELECT count(height) as blockCount
FROM blocks
WHERE stale = 0`;
if (poolId) {
query += ` AND pool_id = ?`;
let query;
if (!poolId && !interval) {
// optimized query to get full indexed block count
query = `SELECT CAST(COALESCE(MAX(height) - MIN(height) + 1, 0) AS SIGNED) as blockCount FROM blocks`;
} else if (!poolId) {
// optimized query for indexed count within an interval
query = `SELECT GREATEST(0, COALESCE(
CAST((SELECT height FROM blocks WHERE stale = 0 AND blockTimestamp <= NOW() ORDER BY blockTimestamp DESC LIMIT 1) AS SIGNED) -
CAST((SELECT height FROM blocks WHERE stale = 0 AND blockTimestamp >= DATE_SUB(NOW(), INTERVAL ${interval}) ORDER BY blockTimestamp ASC LIMIT 1) AS SIGNED) + 1
, 0)) as blockCount`;
} else {
// for specific pools, we do still have to actually count the blocks
query = `SELECT count(*) as blockCount
FROM blocks
WHERE stale = 0 AND pool_id = ?`;
params.push(poolId);
}
if (interval) {
query += ` AND blockTimestamp BETWEEN DATE_SUB(NOW(), INTERVAL ${interval}) AND NOW()`;
if (interval) {
query += ` AND blockTimestamp BETWEEN DATE_SUB(NOW(), INTERVAL ${interval}) AND NOW()`;
}
}
try {

View file

@ -38,6 +38,7 @@ class PoolsRepository {
let query = `
SELECT
COUNT(blocks.height) As blockCount,
COUNT(CASE WHEN blocks.tx_count = 1 THEN 1 END) AS emptyBlocks,
pool_id AS poolId,
pools.name AS name,
pools.link AS link,
@ -47,7 +48,7 @@ class PoolsRepository {
unique_id as poolUniqueId
FROM blocks
JOIN pools on pools.id = pool_id
LEFT JOIN blocks_audits ON blocks_audits.height = blocks.height
LEFT JOIN blocks_audits ON blocks_audits.hash = blocks.hash
WHERE blocks.stale = 0
`;