Skip to content

Commit 59e6783

Browse files
committed
Run list now filters by a single runtime environment
1 parent 234af54 commit 59e6783

File tree

14 files changed

+110
-101
lines changed

14 files changed

+110
-101
lines changed

apps/webapp/app/components/runs/v3/TaskRunsTable.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,7 @@ function BlankState({ isLoading, filters }: Pick<RunsTableProps, "isLoading" | "
539539
const environment = useEnvironment();
540540
if (isLoading) return <TableBlankRow colSpan={15}></TableBlankRow>;
541541

542-
const { environments, tasks, from, to, ...otherFilters } = filters;
542+
const { tasks, from, to, ...otherFilters } = filters;
543543

544544
if (
545545
filters.tasks.length === 1 &&

apps/webapp/app/models/runtimeEnvironment.server.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,3 +275,36 @@ export function displayableEnvironment(
275275
userName,
276276
};
277277
}
278+
279+
export async function findDisplayableEnvironment(
280+
environmentId: string,
281+
userId: string | undefined
282+
) {
283+
const environment = await prisma.runtimeEnvironment.findFirst({
284+
where: {
285+
id: environmentId,
286+
},
287+
select: {
288+
id: true,
289+
type: true,
290+
slug: true,
291+
orgMember: {
292+
select: {
293+
user: {
294+
select: {
295+
id: true,
296+
name: true,
297+
displayName: true,
298+
},
299+
},
300+
},
301+
},
302+
},
303+
});
304+
305+
if (!environment) {
306+
return;
307+
}
308+
309+
return displayableEnvironment(environment, userId);
310+
}

apps/webapp/app/models/task.server.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { PrismaClientOrTransaction, sqlDatabaseSchema } from "~/db.server";
77
* It has indexes for fast performance.
88
* It does NOT care about versions, so includes all tasks ever created.
99
*/
10-
export function getAllTaskIdentifiers(prisma: PrismaClientOrTransaction, projectId: string) {
10+
export function getAllTaskIdentifiers(prisma: PrismaClientOrTransaction, environmentId: string) {
1111
return prisma.$queryRaw<
1212
{
1313
slug: string;
@@ -16,6 +16,6 @@ export function getAllTaskIdentifiers(prisma: PrismaClientOrTransaction, project
1616
>`
1717
SELECT DISTINCT(slug), "triggerSource"
1818
FROM ${sqlDatabaseSchema}."BackgroundWorkerTask"
19-
WHERE "projectId" = ${projectId}
19+
WHERE "runtimeEnvironmentId" = ${environmentId}
2020
ORDER BY slug ASC;`;
2121
}

apps/webapp/app/presenters/v3/ApiRunListPresenter.server.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { CoercedDate } from "~/utils/zod";
1212
import { ApiRetrieveRunPresenter } from "./ApiRetrieveRunPresenter.server";
1313
import { type RunListOptions, RunListPresenter } from "./RunListPresenter.server";
1414
import { BasePresenter } from "./basePresenter.server";
15+
import { ServiceValidationError } from "~/v3/services/baseService.server";
1516

1617
export const ApiRunListSearchParams = z.object({
1718
"page[size]": z.coerce.number().int().positive().min(1).max(100).optional(),
@@ -134,9 +135,11 @@ export class ApiRunListPresenter extends BasePresenter {
134135
options.direction = "backward";
135136
}
136137

138+
let environmentId: string | undefined;
139+
137140
// filters
138141
if (environment) {
139-
options.environments = [environment.id];
142+
environmentId = environment.id;
140143
} else {
141144
if (searchParams["filter[env]"]) {
142145
const environments = await this._prisma.runtimeEnvironment.findMany({
@@ -148,10 +151,14 @@ export class ApiRunListPresenter extends BasePresenter {
148151
},
149152
});
150153

151-
options.environments = environments.map((env) => env.id);
154+
environmentId = environments.at(0)?.id;
152155
}
153156
}
154157

158+
if (!environmentId) {
159+
throw new ServiceValidationError("No environment found");
160+
}
161+
155162
if (searchParams["filter[status]"]) {
156163
options.statuses = searchParams["filter[status]"].flatMap((status) =>
157164
ApiRunListPresenter.apiStatusToRunStatuses(status)
@@ -202,7 +209,7 @@ export class ApiRunListPresenter extends BasePresenter {
202209

203210
logger.debug("Calling RunListPresenter", { options });
204211

205-
const results = await presenter.call(options);
212+
const results = await presenter.call(environmentId, options);
206213

207214
logger.debug("RunListPresenter results", { results });
208215

apps/webapp/app/presenters/v3/RunListPresenter.server.ts

Lines changed: 46 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { Prisma, type TaskRunStatus } from "@trigger.dev/database";
22
import parse from "parse-duration";
3+
import { type Direction } from "~/components/ListPagination";
4+
import { timeFilters } from "~/components/runs/v3/SharedFilters";
35
import { sqlDatabaseSchema } from "~/db.server";
4-
import { displayableEnvironment } from "~/models/runtimeEnvironment.server";
6+
import { findDisplayableEnvironment } from "~/models/runtimeEnvironment.server";
7+
import { getAllTaskIdentifiers } from "~/models/task.server";
58
import { isCancellableRunStatus, isFinalRunStatus, isPendingRunStatus } from "~/v3/taskStatus";
69
import { BasePresenter } from "./basePresenter.server";
7-
import { getAllTaskIdentifiers } from "~/models/task.server";
8-
import { type Direction } from "~/components/ListPagination";
9-
import { timeFilters } from "~/components/runs/v3/SharedFilters";
10+
import { ServiceValidationError } from "~/v3/services/baseService.server";
1011

1112
export type RunListOptions = {
1213
userId?: string;
@@ -15,7 +16,6 @@ export type RunListOptions = {
1516
tasks?: string[];
1617
versions?: string[];
1718
statuses?: TaskRunStatus[];
18-
environments?: string[];
1919
tags?: string[];
2020
scheduleId?: string;
2121
period?: string;
@@ -39,27 +39,29 @@ export type RunListItem = RunList["runs"][0];
3939
export type RunListAppliedFilters = RunList["filters"];
4040

4141
export class RunListPresenter extends BasePresenter {
42-
public async call({
43-
userId,
44-
projectId,
45-
tasks,
46-
versions,
47-
statuses,
48-
environments,
49-
tags,
50-
scheduleId,
51-
period,
52-
bulkId,
53-
isTest,
54-
rootOnly,
55-
batchId,
56-
runIds,
57-
from,
58-
to,
59-
direction = "forward",
60-
cursor,
61-
pageSize = DEFAULT_PAGE_SIZE,
62-
}: RunListOptions) {
42+
public async call(
43+
environmentId: string,
44+
{
45+
userId,
46+
projectId,
47+
tasks,
48+
versions,
49+
statuses,
50+
tags,
51+
scheduleId,
52+
period,
53+
bulkId,
54+
isTest,
55+
rootOnly,
56+
batchId,
57+
runIds,
58+
from,
59+
to,
60+
direction = "forward",
61+
cursor,
62+
pageSize = DEFAULT_PAGE_SIZE,
63+
}: RunListOptions
64+
) {
6365
//get the time values from the raw values (including a default period)
6466
const time = timeFilters({
6567
period,
@@ -82,54 +84,35 @@ export class RunListPresenter extends BasePresenter {
8284
rootOnly === true ||
8385
!time.isDefault;
8486

85-
// Find the project scoped to the organization
86-
const project = await this._replica.project.findFirstOrThrow({
87-
select: {
88-
id: true,
89-
environments: {
90-
select: {
91-
id: true,
92-
type: true,
93-
slug: true,
94-
orgMember: {
95-
select: {
96-
user: {
97-
select: {
98-
id: true,
99-
name: true,
100-
displayName: true,
101-
},
102-
},
103-
},
104-
},
105-
},
106-
},
107-
},
108-
where: {
109-
id: projectId,
110-
},
111-
});
112-
11387
//get all possible tasks
114-
const possibleTasksAsync = getAllTaskIdentifiers(this._replica, project.id);
88+
const possibleTasksAsync = getAllTaskIdentifiers(this._replica, environmentId);
11589

11690
//get possible bulk actions
91+
// TODO: we should replace this with the new bulk stuff and make it environment scoped
11792
const bulkActionsAsync = this._replica.bulkActionGroup.findMany({
11893
select: {
11994
friendlyId: true,
12095
type: true,
12196
createdAt: true,
12297
},
12398
where: {
124-
projectId: project.id,
99+
projectId: projectId,
125100
},
126101
orderBy: {
127102
createdAt: "desc",
128103
},
129104
take: 20,
130105
});
131106

132-
const [possibleTasks, bulkActions] = await Promise.all([possibleTasksAsync, bulkActionsAsync]);
107+
const [possibleTasks, bulkActions, displayableEnvironment] = await Promise.all([
108+
possibleTasksAsync,
109+
bulkActionsAsync,
110+
findDisplayableEnvironment(environmentId, userId),
111+
]);
112+
113+
if (!displayableEnvironment) {
114+
throw new ServiceValidationError("No environment found");
115+
}
133116

134117
//we can restrict to specific runs using bulkId, or batchId
135118
let restrictToRunIds: undefined | string[] = undefined;
@@ -163,6 +146,7 @@ export class RunListPresenter extends BasePresenter {
163146
},
164147
where: {
165148
friendlyId: batchId,
149+
runtimeEnvironmentId: environmentId,
166150
},
167151
});
168152

@@ -179,6 +163,7 @@ export class RunListPresenter extends BasePresenter {
179163
},
180164
where: {
181165
friendlyId: scheduleId,
166+
projectId: projectId,
182167
},
183168
});
184169

@@ -202,7 +187,6 @@ export class RunListPresenter extends BasePresenter {
202187
runFriendlyId: string;
203188
taskIdentifier: string;
204189
version: string | null;
205-
runtimeEnvironmentId: string;
206190
status: TaskRunStatus;
207191
createdAt: Date;
208192
startedAt: Date | null;
@@ -231,8 +215,7 @@ export class RunListPresenter extends BasePresenter {
231215
tr.number,
232216
tr."friendlyId" AS "runFriendlyId",
233217
tr."taskIdentifier" AS "taskIdentifier",
234-
bw.version AS version,
235-
tr."runtimeEnvironmentId" AS "runtimeEnvironmentId",
218+
tr."taskVersion" AS version,
236219
tr.status AS status,
237220
tr."createdAt" AS "createdAt",
238221
tr."startedAt" AS "startedAt",
@@ -255,11 +238,9 @@ export class RunListPresenter extends BasePresenter {
255238
tr."metadataType" AS "metadataType"
256239
FROM
257240
${sqlDatabaseSchema}."TaskRun" tr
258-
LEFT JOIN
259-
${sqlDatabaseSchema}."BackgroundWorker" bw ON tr."lockedToVersionId" = bw.id
260241
WHERE
261242
-- project
262-
tr."projectId" = ${project.id}
243+
tr."runtimeEnvironmentId" = ${environmentId}
263244
-- cursor
264245
${
265246
cursor
@@ -288,11 +269,6 @@ WHERE
288269
? Prisma.sql`AND tr.status = ANY(ARRAY[${Prisma.join(statuses)}]::"TaskRunStatus"[])`
289270
: Prisma.empty
290271
}
291-
${
292-
environments && environments.length > 0
293-
? Prisma.sql`AND tr."runtimeEnvironmentId" IN (${Prisma.join(environments)})`
294-
: Prisma.empty
295-
}
296272
${scheduleId ? Prisma.sql`AND tr."scheduleId" = ${scheduleId}` : Prisma.empty}
297273
${typeof isTest === "boolean" ? Prisma.sql`AND tr."isTest" = ${isTest}` : Prisma.empty}
298274
${
@@ -314,8 +290,6 @@ WHERE
314290
: Prisma.empty
315291
}
316292
${rootOnly === true ? Prisma.sql`AND tr."rootTaskRunId" IS NULL` : Prisma.empty}
317-
GROUP BY
318-
tr.id, bw.version
319293
ORDER BY
320294
${direction === "forward" ? Prisma.sql`tr.id DESC` : Prisma.sql`tr.id ASC`}
321295
LIMIT ${pageSize + 1}`;
@@ -350,12 +324,7 @@ WHERE
350324
if (!hasAnyRuns) {
351325
const firstRun = await this._replica.taskRun.findFirst({
352326
where: {
353-
projectId: project.id,
354-
runtimeEnvironmentId: environments
355-
? {
356-
in: environments,
357-
}
358-
: undefined,
327+
runtimeEnvironmentId: environmentId,
359328
},
360329
});
361330

@@ -366,12 +335,6 @@ WHERE
366335

367336
return {
368337
runs: runsToReturn.map((run) => {
369-
const environment = project.environments.find((env) => env.id === run.runtimeEnvironmentId);
370-
371-
if (!environment) {
372-
throw new Error(`Environment not found for TaskRun ${run.id}`);
373-
}
374-
375338
const hasFinished = isFinalRunStatus(run.status);
376339

377340
const startedAt = run.startedAt ?? run.lockedAt;
@@ -396,7 +359,7 @@ WHERE
396359
isReplayable: true,
397360
isCancellable: isCancellableRunStatus(run.status),
398361
isPending: isPendingRunStatus(run.status),
399-
environment: displayableEnvironment(environment, userId),
362+
environment: displayableEnvironment,
400363
idempotencyKey: run.idempotencyKey ? run.idempotencyKey : undefined,
401364
ttl: run.ttl ? run.ttl : undefined,
402365
expiredAt: run.expiredAt ? run.expiredAt.toISOString() : undefined,
@@ -428,7 +391,6 @@ WHERE
428391
tasks: tasks || [],
429392
versions: versions || [],
430393
statuses: statuses || [],
431-
environments: environments || [],
432394
from: time.from,
433395
to: time.to,
434396
},

apps/webapp/app/presenters/v3/ViewSchedulePresenter.server.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ type ViewScheduleOptions = {
88
userId?: string;
99
projectId: string;
1010
friendlyId: string;
11+
environmentId: string;
1112
};
1213

1314
export class ViewSchedulePresenter {
@@ -17,7 +18,7 @@ export class ViewSchedulePresenter {
1718
this.#prismaClient = prismaClient;
1819
}
1920

20-
public async call({ userId, projectId, friendlyId }: ViewScheduleOptions) {
21+
public async call({ userId, projectId, friendlyId, environmentId }: ViewScheduleOptions) {
2122
const schedule = await this.#prismaClient.taskSchedule.findFirst({
2223
select: {
2324
id: true,
@@ -76,7 +77,7 @@ export class ViewSchedulePresenter {
7677

7778
const runPresenter = new RunListPresenter(this.#prismaClient);
7879

79-
const { runs } = await runPresenter.call({
80+
const { runs } = await runPresenter.call(environmentId, {
8081
projectId: schedule.project.id,
8182
scheduleId: schedule.id,
8283
pageSize: 5,

0 commit comments

Comments
 (0)