diff --git a/apps/webapp/app/models/schedules.server.ts b/apps/webapp/app/models/schedules.server.ts new file mode 100644 index 0000000000..58e4d9a870 --- /dev/null +++ b/apps/webapp/app/models/schedules.server.ts @@ -0,0 +1,37 @@ +import { Prisma } from "~/db.server"; + +export function scheduleUniqWhereClause( + projectId: string, + scheduleId: string +): Prisma.TaskScheduleWhereUniqueInput { + if (scheduleId.startsWith("sched_")) { + return { + friendlyId: scheduleId, + projectId, + }; + } + + return { + projectId_deduplicationKey: { + projectId, + deduplicationKey: scheduleId, + }, + }; +} + +export function scheduleWhereClause( + projectId: string, + scheduleId: string +): Prisma.TaskScheduleWhereInput { + if (scheduleId.startsWith("sched_")) { + return { + friendlyId: scheduleId, + projectId, + }; + } + + return { + projectId, + deduplicationKey: scheduleId, + }; +} diff --git a/apps/webapp/app/presenters/v3/ViewSchedulePresenter.server.ts b/apps/webapp/app/presenters/v3/ViewSchedulePresenter.server.ts index 3bc1a2b457..f0e955fd04 100644 --- a/apps/webapp/app/presenters/v3/ViewSchedulePresenter.server.ts +++ b/apps/webapp/app/presenters/v3/ViewSchedulePresenter.server.ts @@ -4,6 +4,7 @@ import { displayableEnvironment } from "~/models/runtimeEnvironment.server"; import { clickhouseClient } from "~/services/clickhouseInstance.server"; import { nextScheduledTimestamps } from "~/v3/utils/calculateNextSchedule.server"; import { NextRunListPresenter } from "./NextRunListPresenter.server"; +import { scheduleWhereClause } from "~/models/schedules.server"; type ViewScheduleOptions = { userId?: string; @@ -63,10 +64,7 @@ export class ViewSchedulePresenter { }, active: true, }, - where: { - friendlyId, - projectId, - }, + where: scheduleWhereClause(projectId, friendlyId), }); if (!schedule) { diff --git a/apps/webapp/app/routes/api.v1.schedules.$scheduleId.activate.ts b/apps/webapp/app/routes/api.v1.schedules.$scheduleId.activate.ts index 59a82e6a77..7eb281c052 100644 --- a/apps/webapp/app/routes/api.v1.schedules.$scheduleId.activate.ts +++ b/apps/webapp/app/routes/api.v1.schedules.$scheduleId.activate.ts @@ -1,8 +1,8 @@ import type { ActionFunctionArgs } from "@remix-run/server-runtime"; import { json } from "@remix-run/server-runtime"; -import { truncateSync } from "fs"; import { z } from "zod"; import { prisma } from "~/db.server"; +import { scheduleUniqWhereClause, scheduleWhereClause } from "~/models/schedules.server"; import { ViewSchedulePresenter } from "~/presenters/v3/ViewSchedulePresenter.server"; import { authenticateApiRequest } from "~/services/apiAuth.server"; @@ -34,10 +34,10 @@ export async function action({ request, params }: ActionFunctionArgs) { try { const existingSchedule = await prisma.taskSchedule.findFirst({ - where: { - friendlyId: parsedParams.data.scheduleId, - projectId: authenticationResult.environment.projectId, - }, + where: scheduleWhereClause( + authenticationResult.environment.projectId, + parsedParams.data.scheduleId + ), }); if (!existingSchedule) { @@ -45,10 +45,10 @@ export async function action({ request, params }: ActionFunctionArgs) { } await prisma.taskSchedule.update({ - where: { - friendlyId: parsedParams.data.scheduleId, - projectId: authenticationResult.environment.projectId, - }, + where: scheduleUniqWhereClause( + authenticationResult.environment.projectId, + parsedParams.data.scheduleId + ), data: { active: true, }, diff --git a/apps/webapp/app/routes/api.v1.schedules.$scheduleId.deactivate.ts b/apps/webapp/app/routes/api.v1.schedules.$scheduleId.deactivate.ts index 7498160a79..e9b2997116 100644 --- a/apps/webapp/app/routes/api.v1.schedules.$scheduleId.deactivate.ts +++ b/apps/webapp/app/routes/api.v1.schedules.$scheduleId.deactivate.ts @@ -2,6 +2,7 @@ import type { ActionFunctionArgs } from "@remix-run/server-runtime"; import { json } from "@remix-run/server-runtime"; import { z } from "zod"; import { prisma } from "~/db.server"; +import { scheduleUniqWhereClause, scheduleWhereClause } from "~/models/schedules.server"; import { ViewSchedulePresenter } from "~/presenters/v3/ViewSchedulePresenter.server"; import { authenticateApiRequest } from "~/services/apiAuth.server"; @@ -33,10 +34,10 @@ export async function action({ request, params }: ActionFunctionArgs) { try { const existingSchedule = await prisma.taskSchedule.findFirst({ - where: { - friendlyId: parsedParams.data.scheduleId, - projectId: authenticationResult.environment.projectId, - }, + where: scheduleWhereClause( + authenticationResult.environment.projectId, + parsedParams.data.scheduleId + ), }); if (!existingSchedule) { @@ -44,10 +45,10 @@ export async function action({ request, params }: ActionFunctionArgs) { } await prisma.taskSchedule.update({ - where: { - friendlyId: parsedParams.data.scheduleId, - projectId: authenticationResult.environment.projectId, - }, + where: scheduleUniqWhereClause( + authenticationResult.environment.projectId, + parsedParams.data.scheduleId + ), data: { active: false, }, diff --git a/apps/webapp/app/routes/api.v1.schedules.$scheduleId.ts b/apps/webapp/app/routes/api.v1.schedules.$scheduleId.ts index e994852537..b9fc8e2caf 100644 --- a/apps/webapp/app/routes/api.v1.schedules.$scheduleId.ts +++ b/apps/webapp/app/routes/api.v1.schedules.$scheduleId.ts @@ -3,6 +3,7 @@ import { json } from "@remix-run/server-runtime"; import { ScheduleObject, UpdateScheduleOptions } from "@trigger.dev/core/v3"; import { z } from "zod"; import { Prisma, prisma } from "~/db.server"; +import { scheduleUniqWhereClause } from "~/models/schedules.server"; import { ViewSchedulePresenter } from "~/presenters/v3/ViewSchedulePresenter.server"; import { authenticateApiRequest } from "~/services/apiAuth.server"; import { UpsertSchedule } from "~/v3/schedules"; @@ -36,10 +37,10 @@ export async function action({ request, params }: ActionFunctionArgs) { case "DELETE": { try { const deletedSchedule = await prisma.taskSchedule.delete({ - where: { - friendlyId: parsedParams.data.scheduleId, - projectId: authenticationResult.environment.projectId, - }, + where: scheduleUniqWhereClause( + authenticationResult.environment.projectId, + parsedParams.data.scheduleId + ), }); return json( diff --git a/apps/webapp/app/v3/services/upsertTaskSchedule.server.ts b/apps/webapp/app/v3/services/upsertTaskSchedule.server.ts index 6d5fa7d495..f7fa8f4d18 100644 --- a/apps/webapp/app/v3/services/upsertTaskSchedule.server.ts +++ b/apps/webapp/app/v3/services/upsertTaskSchedule.server.ts @@ -7,6 +7,7 @@ import { calculateNextScheduledTimestampFromNow } from "../utils/calculateNextSc import { BaseService, ServiceValidationError } from "./baseService.server"; import { CheckScheduleService } from "./checkSchedule.server"; import { scheduleEngine } from "../scheduleEngine.server"; +import { scheduleWhereClause } from "~/models/schedules.server"; export type UpsertTaskScheduleServiceOptions = UpsertSchedule; @@ -37,9 +38,7 @@ export class UpsertTaskScheduleService extends BaseService { const existingSchedule = schedule.friendlyId ? await this._prisma.taskSchedule.findFirst({ - where: { - friendlyId: schedule.friendlyId, - }, + where: scheduleWhereClause(projectId, schedule.friendlyId), }) : await this._prisma.taskSchedule.findFirst({ where: {