diff --git a/apps/webapp/app/presenters/v3/TaskListPresenter.server.ts b/apps/webapp/app/presenters/v3/TaskListPresenter.server.ts index 5d869d0790..7d820aa536 100644 --- a/apps/webapp/app/presenters/v3/TaskListPresenter.server.ts +++ b/apps/webapp/app/presenters/v3/TaskListPresenter.server.ts @@ -1,19 +1,15 @@ +import { CURRENT_DEPLOYMENT_LABEL } from "@trigger.dev/core/v3/isomorphic"; import { Prisma, - type TaskTriggerSource, - type TaskRunStatus as TaskRunStatusType, - type RuntimeEnvironment, type TaskRunStatus as DBTaskRunStatus, + type TaskRunStatus as TaskRunStatusType, + type TaskTriggerSource, } from "@trigger.dev/database"; import { QUEUED_STATUSES } from "~/components/runs/v3/TaskRunStatus"; +import { TaskRunStatus } from "~/database-types"; import { sqlDatabaseSchema } from "~/db.server"; -import type { Organization } from "~/models/organization.server"; -import type { Project } from "~/models/project.server"; -import type { User } from "~/models/user.server"; import { logger } from "~/services/logger.server"; import { BasePresenter } from "./basePresenter.server"; -import { TaskRunStatus } from "~/database-types"; -import { CURRENT_DEPLOYMENT_LABEL } from "@trigger.dev/core/v3/isomorphic"; export type TaskListItem = { slug: string; @@ -27,34 +23,7 @@ type Return = Awaited>; export type TaskActivity = Awaited[string]; export class TaskListPresenter extends BasePresenter { - public async call({ - userId, - projectSlug, - organizationSlug, - environmentSlug, - }: { - userId: User["id"]; - projectSlug: Project["slug"]; - organizationSlug: Organization["slug"]; - environmentSlug: RuntimeEnvironment["slug"]; - }) { - const environment = await this._replica.runtimeEnvironment.findFirstOrThrow({ - select: { - id: true, - type: true, - projectId: true, - }, - where: { - slug: environmentSlug, - project: { - slug: projectSlug, - }, - organization: { - slug: organizationSlug, - }, - }, - }); - + public async call({ environmentId, projectId }: { environmentId: string; projectId: string }) { const tasks = await this._replica.$queryRaw< { id: string; @@ -69,13 +38,13 @@ export class TaskListPresenter extends BasePresenter { FROM ${sqlDatabaseSchema}."WorkerDeploymentPromotion" wdp INNER JOIN ${sqlDatabaseSchema}."WorkerDeployment" wd ON wd.id = wdp."deploymentId" - WHERE wdp."environmentId" = ${environment.id} + WHERE wdp."environmentId" = ${environmentId} AND wdp."label" = ${CURRENT_DEPLOYMENT_LABEL} ), workers AS ( SELECT DISTINCT ON ("runtimeEnvironmentId") id, "runtimeEnvironmentId", version FROM ${sqlDatabaseSchema}."BackgroundWorker" - WHERE "runtimeEnvironmentId" = ${environment.id} + WHERE "runtimeEnvironmentId" = ${environmentId} OR id IN (SELECT id FROM non_dev_workers) ORDER BY "runtimeEnvironmentId", "createdAt" DESC ) @@ -87,23 +56,23 @@ export class TaskListPresenter extends BasePresenter { //then get the activity for each task const activity = this.#getActivity( tasks.map((t) => t.slug), - environment.projectId, - environment.id + projectId, + environmentId ); const runningStats = this.#getRunningStats( tasks.map((t) => t.slug), - environment.projectId, - environment.id + projectId, + environmentId ); const durations = this.#getAverageDurations( tasks.map((t) => t.slug), - environment.projectId, - environment.id + projectId, + environmentId ); - return { tasks, environment, activity, runningStats, durations }; + return { tasks, activity, runningStats, durations }; } async #getActivity(tasks: string[], projectId: string, environmentId: string) { diff --git a/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam._index/route.tsx b/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam._index/route.tsx index 74981b2756..2984e65fdc 100644 --- a/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam._index/route.tsx +++ b/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam._index/route.tsx @@ -70,6 +70,8 @@ import { useEventSource } from "~/hooks/useEventSource"; import { useOrganization } from "~/hooks/useOrganizations"; import { useProject } from "~/hooks/useProject"; import { useTextFilter } from "~/hooks/useTextFilter"; +import { findProjectBySlug } from "~/models/project.server"; +import { findEnvironmentBySlug } from "~/models/runtimeEnvironment.server"; import { type TaskActivity, type TaskListItem, @@ -104,20 +106,33 @@ export const loader = async ({ request, params }: LoaderFunctionArgs) => { const userId = await requireUserId(request); const { organizationSlug, projectParam, envParam } = EnvironmentParamSchema.parse(params); + const project = await findProjectBySlug(organizationSlug, projectParam, userId); + if (!project) { + throw new Response(undefined, { + status: 404, + statusText: "Project not found", + }); + } + + const environment = await findEnvironmentBySlug(project.id, envParam, userId); + if (!environment) { + throw new Response(undefined, { + status: 404, + statusText: "Environment not found", + }); + } + try { const presenter = new TaskListPresenter(); - const { tasks, environment, activity, runningStats, durations } = await presenter.call({ - userId, - organizationSlug, - projectSlug: projectParam, - environmentSlug: envParam, + const { tasks, activity, runningStats, durations } = await presenter.call({ + environmentId: environment.id, + projectId: project.id, }); const usefulLinksPreference = await getUsefulLinksPreference(request); return typeddefer({ tasks, - environment, activity, runningStats, durations, diff --git a/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx b/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx index 99fa18a827..6205336d75 100644 --- a/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx +++ b/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx @@ -104,9 +104,20 @@ export const action: ActionFunction = async ({ request, params }) => { return json(submission); } + const project = await findProjectBySlug(organizationSlug, projectParam, userId); + if (!project) { + return redirectBackWithErrorMessage(request, "Project not found"); + } + + const environment = await findEnvironmentBySlug(project.id, envParam, userId); + + if (!environment) { + return redirectBackWithErrorMessage(request, "Environment not found"); + } + const testService = new TestTaskService(); try { - const run = await testService.call(userId, submission.value); + const run = await testService.call(environment, submission.value); if (!run) { return redirectBackWithErrorMessage( diff --git a/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test/route.tsx b/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test/route.tsx index 0467e9c6fd..ce90133253 100644 --- a/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test/route.tsx +++ b/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test/route.tsx @@ -80,11 +80,6 @@ export default function Page() { const { tasks } = useTypedLoaderData(); const { taskParam } = useParams(); - const navigation = useNavigation(); - - const isLoadingTasks = - navigation.state === "loading" && navigation.location.pathname === location.pathname; - return ( diff --git a/apps/webapp/app/v3/services/testTask.server.ts b/apps/webapp/app/v3/services/testTask.server.ts index 94270f6d06..740f64156e 100644 --- a/apps/webapp/app/v3/services/testTask.server.ts +++ b/apps/webapp/app/v3/services/testTask.server.ts @@ -1,33 +1,25 @@ import { stringifyIO } from "@trigger.dev/core/v3"; -import { findEnvironmentById } from "~/models/runtimeEnvironment.server"; +import { AuthenticatedEnvironment } from "~/services/apiAuth.server"; import { TestTaskData } from "../testTask"; import { BaseService } from "./baseService.server"; import { TriggerTaskService } from "./triggerTask.server"; export class TestTaskService extends BaseService { - public async call(userId: string, data: TestTaskData) { - const authenticatedEnvironment = await findEnvironmentById(data.environmentId); - if (!authenticatedEnvironment) { - return; - } - + public async call(environment: AuthenticatedEnvironment, data: TestTaskData) { const triggerTaskService = new TriggerTaskService(); switch (data.triggerSource) { - case "STANDARD": - const result = await triggerTaskService.call( - data.taskIdentifier, - authenticatedEnvironment, - { - payload: data.payload, - options: { - test: true, - metadata: data.metadata, - }, - } - ); + case "STANDARD": { + const result = await triggerTaskService.call(data.taskIdentifier, environment, { + payload: data.payload, + options: { + test: true, + metadata: data.metadata, + }, + }); return result?.run; + } case "SCHEDULED": { const payload = { scheduleId: "sched_1234", @@ -42,7 +34,7 @@ export class TestTaskService extends BaseService { const result = await triggerTaskService.call( data.taskIdentifier, - authenticatedEnvironment, + environment, { payload: payloadPacket.data, options: { payloadType: payloadPacket.dataType, test: true },