From cb0c404378228a688c14b0fb5d084d52b7db16c9 Mon Sep 17 00:00:00 2001 From: Thomas <4159106+dtslvr@users.noreply.github.com> Date: Mon, 31 Jul 2023 21:41:19 +0200 Subject: [PATCH] Optimize data gathering in import --- apps/api/src/app/import/import.service.ts | 27 ++++++++++++++++++++++ apps/api/src/app/order/order.controller.ts | 17 +++++++++++++- apps/api/src/app/order/order.service.ts | 23 +++++------------- 3 files changed, 49 insertions(+), 18 deletions(-) diff --git a/apps/api/src/app/import/import.service.ts b/apps/api/src/app/import/import.service.ts index 6a41b0b81..96d0262bf 100644 --- a/apps/api/src/app/import/import.service.ts +++ b/apps/api/src/app/import/import.service.ts @@ -8,6 +8,7 @@ import { import { OrderService } from '@ghostfolio/api/app/order/order.service'; import { PlatformService } from '@ghostfolio/api/app/platform/platform.service'; import { PortfolioService } from '@ghostfolio/api/app/portfolio/portfolio.service'; +import { DataGatheringService } from '@ghostfolio/api/services/data-gathering/data-gathering.service'; import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service'; @@ -31,6 +32,7 @@ import { v4 as uuidv4 } from 'uuid'; export class ImportService { public constructor( private readonly accountService: AccountService, + private readonly dataGatheringService: DataGatheringService, private readonly dataProviderService: DataProviderService, private readonly exchangeRateDataService: ExchangeRateDataService, private readonly orderService: OrderService, @@ -355,6 +357,7 @@ export class ImportService { assetProfile.currency, userCurrency ), + SymbolProfile: assetProfile, valueInBaseCurrency: this.exchangeRateDataService.toCurrency( value, assetProfile.currency, @@ -363,6 +366,30 @@ export class ImportService { }); } + activities.sort((activity1, activity2) => { + return Number(activity1.date) - Number(activity2.date); + }); + + if (!isDryRun) { + // Gather symbol data in the background, if not dry run + const uniqueActivities = uniqBy(activities, ({ SymbolProfile }) => { + return getAssetProfileIdentifier({ + dataSource: SymbolProfile.dataSource, + symbol: SymbolProfile.symbol + }); + }); + + this.dataGatheringService.gatherSymbols( + uniqueActivities.map(({ date, SymbolProfile }) => { + return { + date, + dataSource: SymbolProfile.dataSource, + symbol: SymbolProfile.symbol + }; + }) + ); + } + return activities; } diff --git a/apps/api/src/app/order/order.controller.ts b/apps/api/src/app/order/order.controller.ts index c478860d2..0e617462e 100644 --- a/apps/api/src/app/order/order.controller.ts +++ b/apps/api/src/app/order/order.controller.ts @@ -2,6 +2,7 @@ import { RedactValuesInResponseInterceptor } from '@ghostfolio/api/interceptors/ import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request.interceptor'; import { TransformDataSourceInResponseInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-response.interceptor'; import { ApiService } from '@ghostfolio/api/services/api/api.service'; +import { DataGatheringService } from '@ghostfolio/api/services/data-gathering/data-gathering.service'; import { ImpersonationService } from '@ghostfolio/api/services/impersonation/impersonation.service'; import { HEADER_KEY_IMPERSONATION } from '@ghostfolio/common/config'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; @@ -36,6 +37,7 @@ import { UpdateOrderDto } from './update-order.dto'; export class OrderController { public constructor( private readonly apiService: ApiService, + private readonly dataGatheringService: DataGatheringService, private readonly impersonationService: ImpersonationService, private readonly orderService: OrderService, @Inject(REQUEST) private readonly request: RequestWithUser @@ -123,7 +125,7 @@ export class OrderController { ); } - return this.orderService.createOrder({ + const order = await this.orderService.createOrder({ ...data, date: parseISO(data.date), SymbolProfile: { @@ -144,6 +146,19 @@ export class OrderController { User: { connect: { id: this.request.user.id } }, userId: this.request.user.id }); + + if (!order.isDraft) { + // Gather symbol data in the background, if not draft + this.dataGatheringService.gatherSymbols([ + { + dataSource: data.dataSource, + date: order.date, + symbol: data.symbol + } + ]); + } + + return order; } @Put(':id') diff --git a/apps/api/src/app/order/order.service.ts b/apps/api/src/app/order/order.service.ts index 2bce5987a..0f7da5da3 100644 --- a/apps/api/src/app/order/order.service.ts +++ b/apps/api/src/app/order/order.service.ts @@ -118,7 +118,7 @@ export class OrderService { }; } - await this.dataGatheringService.addJobToQueue({ + this.dataGatheringService.addJobToQueue({ data: { dataSource: data.SymbolProfile.connectOrCreate.create.dataSource, symbol: data.SymbolProfile.connectOrCreate.create.symbol @@ -133,22 +133,6 @@ export class OrderService { } }); - const isDraft = - data.type === 'LIABILITY' - ? false - : isAfter(data.date as Date, endOfToday()); - - if (!isDraft) { - // Gather symbol data of order in the background, if not draft - this.dataGatheringService.gatherSymbols([ - { - dataSource: data.SymbolProfile.connectOrCreate.create.dataSource, - date: data.date, - symbol: data.SymbolProfile.connectOrCreate.create.symbol - } - ]); - } - delete data.accountId; delete data.assetClass; delete data.assetSubClass; @@ -166,6 +150,11 @@ export class OrderService { const orderData: Prisma.OrderCreateInput = data; + const isDraft = + data.type === 'LIABILITY' + ? false + : isAfter(data.date as Date, endOfToday()); + const order = await this.prismaService.order.create({ data: { ...orderData,