From 3312f9d7c2be76ef92629217c8b8d4df2c3969a0 Mon Sep 17 00:00:00 2001 From: Ivan Atanasov Date: Wed, 30 Oct 2024 16:40:36 +0100 Subject: [PATCH] optimize the loading of statistics --- .../repositories/workflow.repository.ts | 10 +++++++++- packages/cli/src/requests.ts | 11 +++++++++- .../services/workflow-statistics.service.ts | 18 +++++++++++++++++ .../cli/src/workflows/workflow.service.ts | 20 +++++++------------ 4 files changed, 44 insertions(+), 15 deletions(-) diff --git a/packages/cli/src/databases/repositories/workflow.repository.ts b/packages/cli/src/databases/repositories/workflow.repository.ts index 0317124472..7b468198b8 100644 --- a/packages/cli/src/databases/repositories/workflow.repository.ts +++ b/packages/cli/src/databases/repositories/workflow.repository.ts @@ -95,7 +95,11 @@ export class WorkflowRepository extends Repository { .execute(); } - async getMany(sharedWorkflowIds: string[], options?: ListQuery.Options) { + async getMany( + sharedWorkflowIds: string[], + options?: ListQuery.Options, + includeExecutionStatistics?: boolean, + ) { if (sharedWorkflowIds.length === 0) return { workflows: [], count: 0 }; if (typeof options?.filter?.projectId === 'string' && options.filter.projectId !== '') { @@ -143,6 +147,10 @@ export class WorkflowRepository extends Repository { if (isOwnedByIncluded) relations.push('shared', 'shared.project'); + if (includeExecutionStatistics === true) { + relations.push('statistics'); + } + if (typeof where.name === 'string' && where.name !== '') { where.name = Like(`%${where.name}%`); } diff --git a/packages/cli/src/requests.ts b/packages/cli/src/requests.ts index 4765ac1fad..9a376dba6a 100644 --- a/packages/cli/src/requests.ts +++ b/packages/cli/src/requests.ts @@ -81,7 +81,14 @@ export namespace ListQuery { * Slim workflow returned from a list query operation. */ export namespace Workflow { - type OptionalBaseFields = 'name' | 'active' | 'versionId' | 'createdAt' | 'updatedAt' | 'tags'; + type OptionalBaseFields = + | 'name' + | 'active' + | 'versionId' + | 'createdAt' + | 'updatedAt' + | 'tags' + | 'statistics'; type BaseFields = Pick & Partial>; @@ -89,10 +96,12 @@ export namespace ListQuery { type SharedField = Partial>; type OwnedByField = { ownedBy: SlimUser | null; homeProject: SlimProject | null }; + type ExecutionStatisticsField = { executionStatistics: { errors: number; successes: number } }; export type Plain = BaseFields; export type WithSharing = BaseFields & SharedField; + export type WithExecutionStatistics = BaseFields & ExecutionStatisticsField; export type WithOwnership = BaseFields & OwnedByField; diff --git a/packages/cli/src/services/workflow-statistics.service.ts b/packages/cli/src/services/workflow-statistics.service.ts index 005db8c5fd..7fe7a07d81 100644 --- a/packages/cli/src/services/workflow-statistics.service.ts +++ b/packages/cli/src/services/workflow-statistics.service.ts @@ -7,6 +7,7 @@ import { WorkflowStatisticsRepository } from '@/databases/repositories/workflow- import { EventService } from '@/events/event.service'; import type { WorkflowStatisticsData } from '@/interfaces'; import { Logger } from '@/logging/logger.service'; +import type { ListQuery } from '@/requests'; import { UserService } from '@/services/user.service'; import { TypedEmitter } from '@/typed-emitter'; @@ -169,4 +170,21 @@ export class WorkflowStatisticsService extends TypedEmitter s.name === StatisticsNames.productionError)?.count ?? 0, + successes: + workflowStatistics?.find((s) => s.name === StatisticsNames.productionSuccess)?.count ?? 0, + }, + }); + + delete entity.statistics; + return entity; + } } diff --git a/packages/cli/src/workflows/workflow.service.ts b/packages/cli/src/workflows/workflow.service.ts index a430cf7298..5c33234967 100644 --- a/packages/cli/src/workflows/workflow.service.ts +++ b/packages/cli/src/workflows/workflow.service.ts @@ -70,7 +70,11 @@ export class WorkflowService { }); // eslint-disable-next-line prefer-const - let { workflows, count } = await this.workflowRepository.getMany(sharedWorkflowIds, options); + let { workflows, count } = await this.workflowRepository.getMany( + sharedWorkflowIds, + options, + includeExecutionStatistics, + ); if (hasSharing(workflows)) { workflows = workflows.map((w) => this.ownershipService.addOwnedByAndSharedWith(w)); @@ -82,21 +86,11 @@ export class WorkflowService { } if (includeExecutionStatistics) { - workflows = await Promise.all( - workflows.map(async (w) => { - const stats = await this.workflowStatisticsService.getData(w.id, 'count', 0); - return { - ...w, - executionStatistics: { - errors: stats.productionError, - successes: stats.productionSuccess, - }, - }; - }), - ); + workflows = workflows.map((w) => this.workflowStatisticsService.addExecutionStatistics(w)); } workflows.forEach((w) => { + // @ts-expect-error: This is to emulate the old behaviour of removing the shared // field as part of `addOwnedByAndSharedWith`. We need this field in `addScopes` // though. So to avoid leaking the information we just delete it. delete w.shared;