Browse Source

Fix portfolio snapshot cache write and initialization retry limit

pull/7517/head
Thomas Kaul 4 weeks ago
parent
commit
727373bcb6
  1. 12
      apps/api/src/app/portfolio/calculator/portfolio-calculator.ts
  2. 2
      apps/api/src/services/queues/portfolio-snapshot/portfolio-snapshot.processor.ts
  3. 14
      apps/api/src/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock.ts

12
apps/api/src/app/portfolio/calculator/portfolio-calculator.ts

@ -65,6 +65,8 @@ import { isNumber, sortBy, sum, uniqBy } from 'lodash';
export abstract class PortfolioCalculator {
protected static readonly ENABLE_LOGGING = false;
private static readonly MAX_INITIALIZATION_ATTEMPTS = 3;
protected readonly logger = new Logger(PortfolioCalculator.name);
protected accountBalanceItems: HistoricalDataItem[];
@ -1124,7 +1126,7 @@ export abstract class PortfolioCalculator {
}
@LogPerformance
private async initialize() {
private async initialize(attempt = 1) {
const startTimeTotal = performance.now();
let cachedPortfolioSnapshot: PortfolioSnapshot;
@ -1205,7 +1207,13 @@ export abstract class PortfolioCalculator {
await job.finished();
}
await this.initialize();
if (attempt >= PortfolioCalculator.MAX_INITIALIZATION_ATTEMPTS) {
throw new Error(
`Portfolio snapshot of user '${this.userId}' could not be computed after ${attempt} attempts`
);
}
await this.initialize(attempt + 1);
}
}
}

2
apps/api/src/services/queues/portfolio-snapshot/portfolio-snapshot.processor.ts

@ -87,7 +87,7 @@ export class PortfolioSnapshotProcessor {
: 0
);
this.redisCacheService.set(
await this.redisCacheService.set(
this.redisCacheService.getPortfolioSnapshotKey({
filters: job.data.filters,
userId: job.data.userId

14
apps/api/src/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock.ts

@ -1,4 +1,8 @@
import { PortfolioSnapshotValue } from '@ghostfolio/api/app/portfolio/interfaces/snapshot-value.interface';
import { RedisCacheServiceMock } from '@ghostfolio/api/app/redis-cache/redis-cache.service.mock';
import type { Job, JobId, JobOptions } from 'bull';
import ms from 'ms';
import { setTimeout } from 'timers/promises';
import { PortfolioSnapshotQueueJob } from './interfaces/portfolio-snapshot-queue-job.interface';
@ -15,7 +19,15 @@ export const PortfolioSnapshotServiceMock = {
finished: async () => {
await setTimeout(100);
return Promise.resolve();
// Mimic the processor which caches the computed portfolio snapshot
// under the job id
await RedisCacheServiceMock.set(
opts?.jobId as string,
JSON.stringify({
expiration: Date.now() + ms('1 minute'),
portfolioSnapshot: {}
} as unknown as PortfolioSnapshotValue)
);
}
};

Loading…
Cancel
Save