Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 1.4k
fix: stop creating TaskRunTag records and join table entries during triggering#3369
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
d63d41f197c3feb5e19ff9f6da36File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| --- | ||
| area: webapp | ||
| type: improvement | ||
| --- | ||
| Stop creating TaskRunTag records and _TaskRunToTaskRunTag join table entries during task triggering. The denormalized runTags string array on TaskRun already stores tag names, making the M2M relation redundant write overhead. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,108 +1 @@ | ||
| import { Prisma } from "@trigger.dev/database"; | ||
| import { prisma } from "~/db.server"; | ||
| import { generateFriendlyId } from "~/v3/friendlyIdentifiers"; | ||
| import { PrismaClientOrTransaction } from "@trigger.dev/database"; | ||
| export const MAX_TAGS_PER_RUN = 10; | ||
| const MAX_RETRIES = 3; | ||
| export async function createTag( | ||
| { tag, projectId }: { tag: string; projectId: string }, | ||
| prismaClient: PrismaClientOrTransaction = prisma | ||
| ) { | ||
| if (tag.trim().length === 0) return; | ||
| let attempts = 0; | ||
| const friendlyId = generateFriendlyId("runtag"); | ||
| while (attempts < MAX_RETRIES) { | ||
| try { | ||
| return await prisma.taskRunTag.upsert({ | ||
| where: { | ||
| projectId_name: { | ||
| projectId, | ||
| name: tag, | ||
| }, | ||
| }, | ||
| create: { | ||
| friendlyId, | ||
| name: tag, | ||
| projectId, | ||
| }, | ||
| update: {}, | ||
| }); | ||
| } catch (error) { | ||
| if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2002") { | ||
| // Handle unique constraint violation (conflict) | ||
| attempts++; | ||
| if (attempts >= MAX_RETRIES) { | ||
| throw new Error(`Failed to create tag after ${MAX_RETRIES} attempts due to conflicts.`); | ||
| } | ||
| } else { | ||
| throw error; // Re-throw other errors | ||
| } | ||
| } | ||
| } | ||
| } | ||
| export type TagRecord = { | ||
| id: string; | ||
| name: string; | ||
| }; | ||
| export async function createTags( | ||
| { | ||
| tags, | ||
| projectId, | ||
| }: { | ||
| tags: string | string[] | undefined; | ||
| projectId: string; | ||
| }, | ||
| prismaClient: PrismaClientOrTransaction = prisma | ||
| ): Promise<TagRecord[]> { | ||
| if (!tags) { | ||
| return []; | ||
| } | ||
| const tagsArray = typeof tags === "string" ? [tags] : tags; | ||
| if (tagsArray.length === 0) { | ||
| return []; | ||
| } | ||
| const tagRecords: TagRecord[] = []; | ||
| for (const tag of tagsArray) { | ||
| const tagRecord = await createTag( | ||
| { | ||
| tag, | ||
| projectId, | ||
| }, | ||
| prismaClient | ||
| ); | ||
| if (tagRecord) { | ||
| tagRecords.push({ id: tagRecord.id, name: tagRecord.name }); | ||
| } | ||
| } | ||
| return tagRecords; | ||
| } | ||
| export async function getTagsForRunId({ | ||
| friendlyId, | ||
| environmentId, | ||
| }: { | ||
| friendlyId: string; | ||
| environmentId: string; | ||
| }) { | ||
| const run = await prisma.taskRun.findFirst({ | ||
| where: { | ||
| friendlyId, | ||
| runtimeEnvironmentId: environmentId, | ||
| }, | ||
| select: { | ||
| tags: true, | ||
| }, | ||
| }); | ||
| return run?.tags ?? undefined; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -2,7 +2,7 @@ import { type ActionFunctionArgs, json } from "@remix-run/server-runtime"; | ||
| import { AddTagsRequestBody } from "@trigger.dev/core/v3"; | ||
| import { z } from "zod"; | ||
| import { prisma } from "~/db.server"; | ||
| import { createTag, getTagsForRunId, MAX_TAGS_PER_RUN } from "~/models/taskRunTag.server"; | ||
| import { MAX_TAGS_PER_RUN } from "~/models/taskRunTag.server"; | ||
| import { authenticateApiRequest } from "~/services/apiAuth.server"; | ||
| const ParamsSchema = z.object({ | ||
| @@ -37,17 +37,23 @@ export async function action({ request, params }: ActionFunctionArgs) { | ||
| return json({ error: "Invalid request body", issues: body.error.issues }, { status: 400 }); | ||
| } | ||
| const existingTags = | ||
| (await getTagsForRunId({ | ||
| const run = await prisma.taskRun.findFirst({ | ||
| where: { | ||
| friendlyId: parsedParams.data.runId, | ||
| environmentId: authenticationResult.environment.id, | ||
| })) ?? []; | ||
| runtimeEnvironmentId: authenticationResult.environment.id, | ||
| }, | ||
| select: { | ||
| runTags: true, | ||
| }, | ||
| }); | ||
| const existingTags = run?.runTags ?? []; | ||
| //remove duplicate tags from the new tags | ||
| const bodyTags = typeof body.data.tags === "string" ? [body.data.tags] : body.data.tags; | ||
| const newTags = bodyTags.filter((tag) => { | ||
| if (tag.trim().length === 0) return false; | ||
| return !existingTags.map((t) => t.name).includes(tag); | ||
| return !existingTags.includes(tag); | ||
| }); | ||
| if (existingTags.length + newTags.length > MAX_TAGS_PER_RUN) { | ||
| @@ -65,29 +71,12 @@ export async function action({ request, params }: ActionFunctionArgs) { | ||
| return json({ message: "No new tags to add" }, { status: 200 }); | ||
| } | ||
| //create tags | ||
| let tagIds: string[] = existingTags.map((t) => t.id); | ||
| if (newTags.length > 0) { | ||
| for (const tag of newTags) { | ||
| const tagRecord = await createTag({ | ||
| tag, | ||
| projectId: authenticationResult.environment.projectId, | ||
| }); | ||
| if (tagRecord) { | ||
| tagIds.push(tagRecord.id); | ||
| } | ||
| } | ||
| } | ||
| await prisma.taskRun.update({ | ||
| where: { | ||
| friendlyId: parsedParams.data.runId, | ||
| runtimeEnvironmentId: authenticationResult.environment.id, | ||
| }, | ||
| data: { | ||
| tags: { | ||
| connect: tagIds.map((id) => ({ id })), | ||
| }, | ||
| runTags: { | ||
| push: newTags, | ||
| }, | ||
ericallam marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -637,13 +637,7 @@ export class RunEngine { | ||
| priorityMs, | ||
| queueTimestamp: queueTimestamp ?? delayUntil ?? new Date(), | ||
| ttl: resolvedTtl, | ||
| tags: | ||
| tags.length === 0 | ||
| ? undefined | ||
| : { | ||
| connect: tags, | ||
| }, | ||
| runTags: tags.length === 0 ? undefined : tags.map((tag) => tag.name), | ||
| runTags: tags.length === 0 ? undefined : tags, | ||
coderabbitai[bot] marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| oneTimeUseToken, | ||
| parentTaskRunId, | ||
| rootTaskRunId, | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -32,7 +32,7 @@ export type DebounceOptions = { | ||
| payloadType: string; | ||
| metadata?: string; | ||
| metadataType?: string; | ||
| tags?: { id: string; name: string }[]; | ||
| tags?: string[]; | ||
| maxAttempts?: number; | ||
| maxDurationInSeconds?: number; | ||
| machine?: string; | ||
| @@ -876,10 +876,7 @@ return 0 | ||
| // Handle tags update - replace existing tags | ||
| if (updateData.tags !== undefined) { | ||
| updatePayload.runTags = updateData.tags.map((t) => t.name); | ||
| updatePayload.tags = { | ||
| set: updateData.tags.map((t) => ({ id: t.id })), | ||
| }; | ||
| updatePayload.runTags = updateData.tags; | ||
coderabbitai[bot] marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| } | ||
| const updatedRun = await prisma.taskRun.update({ | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.