diff --git a/.server-changes/task-list-remove-unused-metrics-queries.md b/.server-changes/task-list-remove-unused-metrics-queries.md new file mode 100644 index 0000000000..23164a205c --- /dev/null +++ b/.server-changes/task-list-remove-unused-metrics-queries.md @@ -0,0 +1,6 @@ +--- +area: webapp +type: fix +--- + +The tasks page no longer runs two queries whose results were never displayed, cutting wasted work on every page load and removing a source of hidden server errors diff --git a/apps/webapp/app/presenters/v3/TaskListPresenter.server.ts b/apps/webapp/app/presenters/v3/TaskListPresenter.server.ts index f62cfef5c7..1541329884 100644 --- a/apps/webapp/app/presenters/v3/TaskListPresenter.server.ts +++ b/apps/webapp/app/presenters/v3/TaskListPresenter.server.ts @@ -6,10 +6,8 @@ import { import { $replica } from "~/db.server"; import { clickhouseFactory } from "~/services/clickhouse/clickhouseFactoryInstance.server"; import { - type AverageDurations, ClickHouseEnvironmentMetricsRepository, type CurrentRunningStats, - type DailyTaskActivity, } from "~/services/environmentMetricsRepository.server"; import { singleton } from "~/utils/singleton"; import { findCurrentWorkerFromEnvironment } from "~/v3/models/workerDeployment.server"; @@ -21,8 +19,6 @@ export type TaskListItem = { triggerSource: TaskTriggerSource; }; -export type TaskActivity = DailyTaskActivity[string]; - export class TaskListPresenter { constructor(private readonly _replica: PrismaClientOrTransaction) {} @@ -55,9 +51,7 @@ export class TaskListPresenter { if (!currentWorker) { return { tasks: [], - activity: Promise.resolve({} as DailyTaskActivity), runningStats: Promise.resolve({} as CurrentRunningStats), - durations: Promise.resolve({} as AverageDurations), }; } @@ -89,16 +83,10 @@ export class TaskListPresenter { clickhouse, }); - // IMPORTANT: Don't await these, we want to return the promises - // so we can defer the loading of the data - const activity = environmentMetricsRepository.getDailyTaskActivity({ - organizationId, - projectId, - environmentId, - days: 6, // This actually means 7 days, because we want to show the current day too - tasks: slugs, - }); - + // IMPORTANT: Don't await this, we want to return the promise + // so we can defer the loading of the data. The caller is responsible for + // consuming it — an unconsumed promise here would become an unhandled + // rejection if the underlying query fails. const runningStats = environmentMetricsRepository.getCurrentRunningStats({ organizationId, projectId, @@ -107,15 +95,7 @@ export class TaskListPresenter { tasks: slugs, }); - const durations = environmentMetricsRepository.getAverageDurations({ - organizationId, - projectId, - environmentId, - days: 6, - tasks: slugs, - }); - - return { tasks, activity, runningStats, durations }; + return { tasks, runningStats }; } } diff --git a/apps/webapp/app/services/environmentMetricsRepository.server.ts b/apps/webapp/app/services/environmentMetricsRepository.server.ts index 61b53a4d6c..5ecdf13f20 100644 --- a/apps/webapp/app/services/environmentMetricsRepository.server.ts +++ b/apps/webapp/app/services/environmentMetricsRepository.server.ts @@ -2,19 +2,9 @@ import { type ClickHouse } from "@internal/clickhouse"; import type { TaskRunStatus } from "@trigger.dev/database"; import { QUEUED_STATUSES } from "~/components/runs/v3/TaskRunStatus"; -export type DailyTaskActivity = Record)[]>; export type CurrentRunningStats = Record; -export type AverageDurations = Record; export interface EnvironmentMetricsRepository { - getDailyTaskActivity(options: { - organizationId: string; - projectId: string; - environmentId: string; - days: number; - tasks: string[]; - }): Promise; - getCurrentRunningStats(options: { organizationId: string; projectId: string; @@ -22,14 +12,6 @@ export interface EnvironmentMetricsRepository { days: number; tasks: string[]; }): Promise; - - getAverageDurations(options: { - organizationId: string; - projectId: string; - environmentId: string; - days: number; - tasks: string[]; - }): Promise; } export type ClickHouseEnvironmentMetricsRepositoryOptions = { @@ -39,45 +21,6 @@ export type ClickHouseEnvironmentMetricsRepositoryOptions = { export class ClickHouseEnvironmentMetricsRepository implements EnvironmentMetricsRepository { constructor(private readonly options: ClickHouseEnvironmentMetricsRepositoryOptions) {} - public async getDailyTaskActivity({ - organizationId, - projectId, - environmentId, - days, - tasks, - }: { - organizationId: string; - projectId: string; - environmentId: string; - days: number; - tasks: string[]; - }): Promise { - if (tasks.length === 0) { - return {}; - } - - const [queryError, activity] = await this.options.clickhouse.taskRuns.getTaskActivity({ - organizationId, - projectId, - environmentId, - days, - }); - - if (queryError) { - throw queryError; - } - - return fillInDailyTaskActivity( - activity.map((a) => ({ - taskIdentifier: a.task_identifier, - status: a.status as TaskRunStatus, - day: new Date(a.day), - count: BigInt(a.count), - })), - days - ); - } - public async getCurrentRunningStats({ organizationId, projectId, @@ -115,82 +58,6 @@ export class ClickHouseEnvironmentMetricsRepository implements EnvironmentMetric tasks ); } - - public async getAverageDurations({ - organizationId, - projectId, - environmentId, - days, - tasks, - }: { - organizationId: string; - projectId: string; - environmentId: string; - days: number; - tasks: string[]; - }): Promise { - if (tasks.length === 0) { - return {}; - } - - const [queryError, durations] = await this.options.clickhouse.taskRuns.getAverageDurations({ - organizationId, - projectId, - environmentId, - days, - }); - - if (queryError) { - throw queryError; - } - - return Object.fromEntries(durations.map((d) => [d.task_identifier, Number(d.duration)])); - } -} - -type TaskActivityResults = Array<{ - taskIdentifier: string; - status: TaskRunStatus; - day: Date; - count: bigint; -}>; - -function fillInDailyTaskActivity(activity: TaskActivityResults, days: number): DailyTaskActivity { - //today with no time - const today = new Date(); - today.setUTCHours(0, 0, 0, 0); - - return activity.reduce((acc, a) => { - let existingTask = acc[a.taskIdentifier]; - - if (!existingTask) { - existingTask = []; - //populate the array with the past 7 days - for (let i = days; i >= 0; i--) { - const day = new Date(today); - day.setUTCDate(today.getDate() - i); - day.setUTCHours(0, 0, 0, 0); - - existingTask.push({ - day: day.toISOString(), - ["COMPLETED_SUCCESSFULLY"]: 0, - } as { day: string } & Record); - } - - acc[a.taskIdentifier] = existingTask; - } - - const dayString = a.day.toISOString(); - const day = existingTask.find((d) => d.day === dayString); - - if (!day) { - return acc; - } - - day[a.status] = Number(a.count); - - return acc; - }, {} as DailyTaskActivity); } type CurrentRunningStatsResults = Array<{