Cache live user agent report off request path

This commit is contained in:
Ben
2026-06-07 22:58:00 -04:00
parent f14d76c2ea
commit eac0fe65ab
2 changed files with 68 additions and 2 deletions
@@ -8,6 +8,8 @@ import { RedisMessagingService } from '../../../services/redis-messaging.service
@Injectable() @Injectable()
export class UserAgentReportService { export class UserAgentReportService {
private readonly liveReportCacheKey = 'presence:user-agent-report';
private liveRefreshPromise: Promise<UserAgentReportView[]> | null = null;
constructor( constructor(
@InjectRepository(UserAgentReportView) @InjectRepository(UserAgentReportView)
@@ -20,6 +22,37 @@ export class UserAgentReportService {
} }
public async getReport() { public async getReport() {
const cachedReport = await this.redisMessagingService
.getJsonCache<UserAgentReportView[]>(this.liveReportCacheKey)
.catch(error => {
console.error(`Live user-agent report cache read failed: ${error.message}`);
return null;
});
if (cachedReport != null) {
return cachedReport;
}
if (process.env.API_ONLY == 'true') {
return this.userAgentReport.find();
}
return this.refreshLiveReport();
}
public async refreshLiveReport() {
if (this.liveRefreshPromise != null) {
return this.liveRefreshPromise;
}
this.liveRefreshPromise = this.buildLiveReport()
.finally(() => {
this.liveRefreshPromise = null;
});
return this.liveRefreshPromise;
}
private async buildLiveReport() {
const presences = await this.redisMessagingService.getAllClientPresence(); const presences = await this.redisMessagingService.getAllClientPresence();
const rows = new Map<string, { const rows = new Map<string, {
userAgent: string; userAgent: string;
@@ -47,7 +80,7 @@ export class UserAgentReportService {
rows.set(userAgent, row); rows.set(userAgent, row);
}); });
return [...rows.values()] const report = [...rows.values()]
.sort((left, right) => right.totalHashRate - left.totalHashRate) .sort((left, right) => right.totalHashRate - left.totalHashRate)
.map(row => ({ .map(row => ({
userAgent: row.userAgent, userAgent: row.userAgent,
@@ -55,11 +88,20 @@ export class UserAgentReportService {
bestDifficulty: row.bestDifficulty, bestDifficulty: row.bestDifficulty,
totalHashRate: row.totalHashRate.toString(), totalHashRate: row.totalHashRate.toString(),
})); }));
await this.redisMessagingService
.setJsonCache(this.liveReportCacheKey, report, 60 * 1000)
.catch(error => {
console.error(`Live user-agent report cache write failed: ${error.message}`);
});
return report;
} }
public async refreshReport() { public async refreshReport() {
try { try {
return await this.userAgentReport.query(`REFRESH MATERIALIZED VIEW user_agent_report_view`); await this.userAgentReport.query(`REFRESH MATERIALIZED VIEW user_agent_report_view`);
return await this.refreshLiveReport();
} catch (e) { } catch (e) {
console.log(e) console.log(e)
+24
View File
@@ -6,6 +6,7 @@ import { RpcBlockService } from '../ORM/rpc-block/rpc-block.service';
@Injectable() @Injectable()
export class AppService implements OnModuleInit { export class AppService implements OnModuleInit {
private refreshingLiveUserAgentReport = false;
constructor( constructor(
private readonly clientService: ClientService, private readonly clientService: ClientService,
@@ -27,6 +28,14 @@ export class AppService implements OnModuleInit {
await this.rpcBlockService.deleteOldBlocks(); await this.rpcBlockService.deleteOldBlocks();
}, 1000 * 60 * 60 * 24); }, 1000 * 60 * 60 * 24);
setInterval(async () => {
await this.refreshLiveUserAgentReport();
}, 1000 * 30);
setTimeout(async () => {
await this.refreshLiveUserAgentReport();
}, 1000 * 15);
setInterval(async () => { setInterval(async () => {
console.log('Refreshing user agent report view') console.log('Refreshing user agent report view')
await this.userAgentReportService.refreshReport(); await this.userAgentReportService.refreshReport();
@@ -43,4 +52,19 @@ export class AppService implements OnModuleInit {
console.log(`Deleted ${deletedClients.affected} old clients`); console.log(`Deleted ${deletedClients.affected} old clients`);
} }
private async refreshLiveUserAgentReport() {
if (this.refreshingLiveUserAgentReport) {
return;
}
this.refreshingLiveUserAgentReport = true;
try {
await this.userAgentReportService.refreshLiveReport();
} catch (error) {
console.error(`Failed refreshing live user agent report: ${error.message}`);
} finally {
this.refreshingLiveUserAgentReport = false;
}
}
} }