Browse Source

Introduce market data page size

feature/optimize-get-range-query-in-market-data-service
Thomas Kaul 7 days ago
parent
commit
e112a6ed9d
  1. 69
      apps/api/src/app/portfolio/current-rate.service.ts
  2. 28
      apps/api/src/services/market-data/market-data.service.ts

69
apps/api/src/app/portfolio/current-rate.service.ts

@ -21,6 +21,8 @@ import { GetValuesParams } from './interfaces/get-values-params.interface';
@Injectable() @Injectable()
export class CurrentRateService { export class CurrentRateService {
private static readonly MARKET_DATA_PAGE_SIZE = 50000;
public constructor( public constructor(
private readonly dataProviderService: DataProviderService, private readonly dataProviderService: DataProviderService,
private readonly marketDataService: MarketDataService, private readonly marketDataService: MarketDataService,
@ -41,30 +43,29 @@ export class CurrentRateService {
(!dateQuery.gte || isBefore(dateQuery.gte, new Date())) && (!dateQuery.gte || isBefore(dateQuery.gte, new Date())) &&
(!dateQuery.in || this.containsToday(dateQuery.in)); (!dateQuery.in || this.containsToday(dateQuery.in));
const promises: Promise<GetValueObject[]>[] = [];
const quoteErrors: ResponseError['errors'] = []; const quoteErrors: ResponseError['errors'] = [];
const today = resetHours(new Date()); const today = resetHours(new Date());
const values: GetValueObject[] = [];
if (includesToday) { if (includesToday) {
promises.push( const quotesBySymbol = await this.dataProviderService.getQuotes({
this.dataProviderService items: dataGatheringItems,
.getQuotes({ items: dataGatheringItems, user: this.request?.user }) user: this.request?.user
.then((dataResultProvider) => { });
const result: GetValueObject[] = [];
for (const { dataSource, symbol } of dataGatheringItems) { for (const { dataSource, symbol } of dataGatheringItems) {
if (dataResultProvider?.[symbol]?.dataProviderInfo) { const quote = quotesBySymbol[symbol];
dataProviderInfos.push(
dataResultProvider[symbol].dataProviderInfo if (quote?.dataProviderInfo) {
); dataProviderInfos.push(quote.dataProviderInfo);
} }
if (dataResultProvider?.[symbol]?.marketPrice) { if (quote?.marketPrice) {
result.push({ values.push({
dataSource, dataSource,
symbol, symbol,
date: today, date: today,
marketPrice: dataResultProvider?.[symbol]?.marketPrice marketPrice: quote.marketPrice
}); });
} else { } else {
quoteErrors.push({ quoteErrors.push({
@ -73,10 +74,6 @@ export class CurrentRateService {
}); });
} }
} }
return result;
})
);
} }
const assetProfileIdentifiers: AssetProfileIdentifier[] = const assetProfileIdentifiers: AssetProfileIdentifier[] =
@ -84,34 +81,42 @@ export class CurrentRateService {
return { dataSource, symbol }; return { dataSource, symbol };
}); });
promises.push( const marketDataCount = await this.marketDataService.getRangeCount({
this.marketDataService
.getRange({
assetProfileIdentifiers, assetProfileIdentifiers,
dateQuery dateQuery
}) });
.then((data) => {
return data.map(({ dataSource, date, marketPrice, symbol }) => { for (
return { let i = 0;
i < marketDataCount;
i += CurrentRateService.MARKET_DATA_PAGE_SIZE
) {
// Use pageSize to limit the number of records fetched at once
const data = await this.marketDataService.getRange({
assetProfileIdentifiers,
dateQuery,
skip: i,
take: CurrentRateService.MARKET_DATA_PAGE_SIZE
});
values.push(
...data.map(({ dataSource, date, marketPrice, symbol }) => ({
dataSource, dataSource,
date, date,
marketPrice, marketPrice,
symbol symbol
}; }))
});
})
); );
}
const values = await Promise.all(promises).then((array) => {
return array.flat();
});
const response: GetValuesObject = { const response: GetValuesObject = {
dataProviderInfos, dataProviderInfos,
errors: quoteErrors.map(({ dataSource, symbol }) => { errors: quoteErrors.map(({ dataSource, symbol }) => {
return { dataSource, symbol }; return { dataSource, symbol };
}), }),
values: uniqBy(values, ({ date, symbol }) => `${date}-${symbol}`) values: uniqBy(values, ({ date, symbol }) => {
return `${date}-${symbol}`;
})
}; };
if (!isEmpty(quoteErrors)) { if (!isEmpty(quoteErrors)) {

28
apps/api/src/services/market-data/market-data.service.ts

@ -60,12 +60,18 @@ export class MarketDataService {
public async getRange({ public async getRange({
assetProfileIdentifiers, assetProfileIdentifiers,
dateQuery dateQuery,
skip,
take
}: { }: {
assetProfileIdentifiers: AssetProfileIdentifier[]; assetProfileIdentifiers: AssetProfileIdentifier[];
dateQuery: DateQuery; dateQuery: DateQuery;
skip?: number;
take?: number;
}): Promise<MarketData[]> { }): Promise<MarketData[]> {
return this.prismaService.marketData.findMany({ return this.prismaService.marketData.findMany({
skip,
take,
orderBy: [ orderBy: [
{ {
date: 'asc' date: 'asc'
@ -86,6 +92,26 @@ export class MarketDataService {
}); });
} }
public async getRangeCount({
assetProfileIdentifiers,
dateQuery
}: {
assetProfileIdentifiers: AssetProfileIdentifier[];
dateQuery: DateQuery;
}): Promise<number> {
return this.prismaService.marketData.count({
where: {
date: dateQuery,
OR: assetProfileIdentifiers.map(({ dataSource, symbol }) => {
return {
dataSource,
symbol
};
})
}
});
}
public async marketDataItems(params: { public async marketDataItems(params: {
select?: Prisma.MarketDataSelectScalar; select?: Prisma.MarketDataSelectScalar;
skip?: number; skip?: number;

Loading…
Cancel
Save