From 6dd6dd396570fc37a9bcce9a469bfceb419432ea Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 29 Nov 2025 13:37:32 +0100 Subject: [PATCH] Introduce maxAge --- apps/api/src/app/admin/admin.controller.ts | 4 +- apps/api/src/services/cron/cron.service.ts | 4 +- .../data-gathering/data-gathering.service.ts | 43 ++++++++++++------- 3 files changed, 32 insertions(+), 19 deletions(-) diff --git a/apps/api/src/app/admin/admin.controller.ts b/apps/api/src/app/admin/admin.controller.ts index 8b5da4965..24467c732 100644 --- a/apps/api/src/app/admin/admin.controller.ts +++ b/apps/api/src/app/admin/admin.controller.ts @@ -93,7 +93,7 @@ export class AdminController { @UseGuards(AuthGuard('jwt'), HasPermissionGuard) public async gatherMax(): Promise { const assetProfileIdentifiers = - await this.dataGatheringService.getAllActiveAssetProfileIdentifiers(); + await this.dataGatheringService.getActiveAssetProfileIdentifiers(); await this.dataGatheringService.addJobsToQueue( assetProfileIdentifiers.map(({ dataSource, symbol }) => { @@ -120,7 +120,7 @@ export class AdminController { @UseGuards(AuthGuard('jwt'), HasPermissionGuard) public async gatherProfileData(): Promise { const assetProfileIdentifiers = - await this.dataGatheringService.getAllActiveAssetProfileIdentifiers(); + await this.dataGatheringService.getActiveAssetProfileIdentifiers(); await this.dataGatheringService.addJobsToQueue( assetProfileIdentifiers.map(({ dataSource, symbol }) => { diff --git a/apps/api/src/services/cron/cron.service.ts b/apps/api/src/services/cron/cron.service.ts index 88fcabce2..ee91a811e 100644 --- a/apps/api/src/services/cron/cron.service.ts +++ b/apps/api/src/services/cron/cron.service.ts @@ -59,7 +59,9 @@ export class CronService { public async runEverySundayAtTwelvePm() { if (await this.isDataGatheringEnabled()) { const assetProfileIdentifiers = - await this.dataGatheringService.getAllActiveAssetProfileIdentifiers(); + await this.dataGatheringService.getActiveAssetProfileIdentifiers({ + maxAge: '60 days' + }); await this.dataGatheringService.addJobsToQueue( assetProfileIdentifiers.map(({ dataSource, symbol }) => { diff --git a/apps/api/src/services/queues/data-gathering/data-gathering.service.ts b/apps/api/src/services/queues/data-gathering/data-gathering.service.ts index f82325f0c..cec63c3eb 100644 --- a/apps/api/src/services/queues/data-gathering/data-gathering.service.ts +++ b/apps/api/src/services/queues/data-gathering/data-gathering.service.ts @@ -28,8 +28,9 @@ import { InjectQueue } from '@nestjs/bull'; import { Inject, Injectable, Logger } from '@nestjs/common'; import { DataSource } from '@prisma/client'; import { JobOptions, Queue } from 'bull'; -import { format, min, subDays, subYears } from 'date-fns'; +import { format, min, subDays, subMilliseconds, subYears } from 'date-fns'; import { isEmpty } from 'lodash'; +import ms, { StringValue } from 'ms'; @Injectable() export class DataGatheringService { @@ -160,8 +161,7 @@ export class DataGatheringService { ); if (!assetProfileIdentifiers) { - assetProfileIdentifiers = - await this.getAllActiveAssetProfileIdentifiers(); + assetProfileIdentifiers = await this.getActiveAssetProfileIdentifiers(); } if (assetProfileIdentifiers.length <= 0) { @@ -301,25 +301,36 @@ export class DataGatheringService { ); } - public async getAllActiveAssetProfileIdentifiers(): Promise< - AssetProfileIdentifier[] - > { - const symbolProfiles = await this.prismaService.symbolProfile.findMany({ - orderBy: [{ symbol: 'asc' }], + /** + * Returns active asset profile identifiers + * + * @param {StringValue} maxAge - Optional. Specifies the maximum allowed age + * of a profile’s last update timestamp. Only asset profiles considered stale + * are returned. + */ + public async getActiveAssetProfileIdentifiers({ + maxAge + }: { + maxAge?: StringValue; + } = {}): Promise { + return this.prismaService.symbolProfile.findMany({ + orderBy: [{ symbol: 'asc' }, { dataSource: 'asc' }], + select: { + dataSource: true, + symbol: true + }, where: { dataSource: { notIn: ['MANUAL', 'RAPID_API'] }, - isActive: true + isActive: true, + ...(maxAge && { + updatedAt: { + lt: subMilliseconds(new Date(), ms(maxAge)) + } + }) } }); - - return symbolProfiles.map(({ dataSource, symbol }) => { - return { - dataSource, - symbol - }; - }); } private async getAssetProfileIdentifiersWithCompleteMarketData(): Promise<