From 93dde1a8998f942c6cafe9e6c11dd893e285811f Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 7 Jun 2026 23:02:57 -0400 Subject: [PATCH] Cache pool accounting summary --- .../share-accounting.service.ts | 23 +++++++++++++++++++ src/services/app.service.ts | 22 +++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/ORM/share-accounting/share-accounting.service.ts b/src/ORM/share-accounting/share-accounting.service.ts index c8aa649..df86a5f 100644 --- a/src/ORM/share-accounting/share-accounting.service.ts +++ b/src/ORM/share-accounting/share-accounting.service.ts @@ -3,6 +3,7 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { AcceptedShareEntity } from '../accepted-share/accepted-share.entity'; +import { RedisMessagingService } from '../../services/redis-messaging.service'; export interface AcceptedShareRecord { protocol: 'sv1' | 'sv2'; @@ -72,6 +73,7 @@ export class ShareAccountingService implements OnModuleDestroy { private flushTimer: NodeJS.Timeout | null = null; private activeFlush: Promise | null = null; private summaryCache = new Map(); + private readonly poolSummaryCacheKey = 'accounting:pool-summary'; private readonly batchSize = this.readPositiveInt('SHARE_ACCOUNTING_BATCH_SIZE', DEFAULT_BATCH_SIZE); private readonly flushIntervalMs = this.readPositiveInt('SHARE_ACCOUNTING_FLUSH_INTERVAL_MS', DEFAULT_FLUSH_INTERVAL_MS); private readonly maxQueueSize = this.readPositiveInt('SHARE_ACCOUNTING_MAX_QUEUE_SIZE', DEFAULT_MAX_QUEUE_SIZE); @@ -81,6 +83,7 @@ export class ShareAccountingService implements OnModuleDestroy { constructor( @InjectRepository(AcceptedShareEntity) private readonly acceptedShareRepository: Repository, + private readonly redisMessagingService?: RedisMessagingService, ) { } public async recordAcceptedShare(record: AcceptedShareRecord): Promise { @@ -127,9 +130,29 @@ export class ShareAccountingService implements OnModuleDestroy { } public async getPoolSummary(): Promise { + const cached = await this.redisMessagingService + ?.getJsonCache(this.poolSummaryCacheKey) + .catch(error => { + console.error(`Pool accounting summary cache read failed: ${error.message}`); + return null; + }); + if (cached != null) { + return cached; + } + return this.getSummary({}); } + public async refreshPoolSummary(): Promise { + const summary = await this.getSummary({}); + await this.redisMessagingService + ?.setJsonCache(this.poolSummaryCacheKey, summary, 60 * 1000) + .catch(error => { + console.error(`Pool accounting summary cache write failed: ${error.message}`); + }); + return summary; + } + public async getAddressSummary(address: string): Promise { return this.getSummary({ address }); } diff --git a/src/services/app.service.ts b/src/services/app.service.ts index d0902ea..4530976 100644 --- a/src/services/app.service.ts +++ b/src/services/app.service.ts @@ -3,15 +3,18 @@ import { Injectable, OnModuleInit } from '@nestjs/common'; import { UserAgentReportService } from '../ORM/_views/user-agent-report/user-agent-report.service'; import { ClientService } from '../ORM/client/client.service'; import { RpcBlockService } from '../ORM/rpc-block/rpc-block.service'; +import { ShareAccountingService } from '../ORM/share-accounting/share-accounting.service'; @Injectable() export class AppService implements OnModuleInit { private refreshingLiveUserAgentReport = false; + private refreshingPoolSummary = false; constructor( private readonly clientService: ClientService, private readonly rpcBlockService: RpcBlockService, - private readonly userAgentReportService: UserAgentReportService + private readonly userAgentReportService: UserAgentReportService, + private readonly shareAccountingService: ShareAccountingService ) { } @@ -30,10 +33,12 @@ export class AppService implements OnModuleInit { setInterval(async () => { await this.refreshLiveUserAgentReport(); + await this.refreshPoolSummary(); }, 1000 * 30); setTimeout(async () => { await this.refreshLiveUserAgentReport(); + await this.refreshPoolSummary(); }, 1000 * 15); setInterval(async () => { @@ -67,4 +72,19 @@ export class AppService implements OnModuleInit { this.refreshingLiveUserAgentReport = false; } } + + private async refreshPoolSummary() { + if (this.refreshingPoolSummary) { + return; + } + + this.refreshingPoolSummary = true; + try { + await this.shareAccountingService.refreshPoolSummary(); + } catch (error) { + console.error(`Failed refreshing pool accounting summary: ${error.message}`); + } finally { + this.refreshingPoolSummary = false; + } + } }