-
-
Notifications
You must be signed in to change notification settings - Fork 645
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Support for batch triggers * Various trace fixes and improvements * Moved trace into the logger, fixed span cardinality issues with waits and triggers * Add support for attaching a debugger in dev with —debugger flag
- Loading branch information
Showing
40 changed files
with
1,262 additions
and
180 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import type { ActionFunctionArgs } from "@remix-run/server-runtime"; | ||
import { json } from "@remix-run/server-runtime"; | ||
import { | ||
parseBatchTriggerTaskRequestBody, | ||
parseTriggerTaskRequestBody, | ||
} from "@trigger.dev/core/v3"; | ||
import { z } from "zod"; | ||
import { MAX_BATCH_TRIGGER_ITEMS } from "~/consts"; | ||
import { authenticateApiRequest } from "~/services/apiAuth.server"; | ||
import { logger } from "~/services/logger.server"; | ||
import { BatchTriggerTaskService } from "~/v3/services/batchTriggerTask.server"; | ||
import { TriggerTaskService } from "~/v3/services/triggerTask.server"; | ||
|
||
const ParamsSchema = z.object({ | ||
taskId: z.string(), | ||
}); | ||
|
||
const HeadersSchema = z.object({ | ||
"idempotency-key": z.string().optional().nullable(), | ||
"trigger-version": z.string().optional().nullable(), | ||
traceparent: z.string().optional(), | ||
tracestate: z.string().optional(), | ||
}); | ||
|
||
export async function action({ request, params }: ActionFunctionArgs) { | ||
// Ensure this is a POST request | ||
if (request.method.toUpperCase() !== "POST") { | ||
return { status: 405, body: "Method Not Allowed" }; | ||
} | ||
|
||
// Next authenticate the request | ||
const authenticationResult = await authenticateApiRequest(request); | ||
|
||
if (!authenticationResult) { | ||
return json({ error: "Invalid or Missing API key" }, { status: 401 }); | ||
} | ||
|
||
const rawHeaders = Object.fromEntries(request.headers); | ||
|
||
const headers = HeadersSchema.safeParse(rawHeaders); | ||
|
||
if (!headers.success) { | ||
return json({ error: "Invalid headers" }, { status: 400 }); | ||
} | ||
|
||
const { | ||
"idempotency-key": idempotencyKey, | ||
"trigger-version": triggerVersion, | ||
traceparent, | ||
tracestate, | ||
} = headers.data; | ||
|
||
const { taskId } = ParamsSchema.parse(params); | ||
|
||
// Now parse the request body | ||
const anyBody = await request.json(); | ||
|
||
const body = parseBatchTriggerTaskRequestBody(anyBody); | ||
|
||
if (!body.success) { | ||
return json({ error: "Invalid request body" }, { status: 400 }); | ||
} | ||
|
||
logger.debug("Triggering batch", { | ||
taskId, | ||
idempotencyKey, | ||
triggerVersion, | ||
body: body.data, | ||
}); | ||
|
||
if (!body.data.items.length) { | ||
return json({ error: "No items to trigger" }, { status: 400 }); | ||
} | ||
|
||
// Check the there are fewer than 100 items | ||
if (body.data.items.length > MAX_BATCH_TRIGGER_ITEMS) { | ||
return json( | ||
{ | ||
error: `Too many items. Maximum allowed batch size is ${MAX_BATCH_TRIGGER_ITEMS}.`, | ||
}, | ||
{ status: 400 } | ||
); | ||
} | ||
|
||
const service = new BatchTriggerTaskService(); | ||
|
||
try { | ||
const result = await service.call(taskId, authenticationResult.environment, body.data, { | ||
idempotencyKey: idempotencyKey ?? undefined, | ||
triggerVersion: triggerVersion ?? undefined, | ||
traceContext: traceparent ? { traceparent, tracestate } : undefined, | ||
}); | ||
|
||
if (!result) { | ||
return json({ error: "Task not found" }, { status: 404 }); | ||
} | ||
|
||
return json({ | ||
batchId: result.batch.friendlyId, | ||
runs: result.runs, | ||
}); | ||
} catch (error) { | ||
if (error instanceof Error) { | ||
return json({ error: error.message }, { status: 400 }); | ||
} | ||
|
||
return json({ error: "Something went wrong" }, { status: 500 }); | ||
} | ||
} |
40 changes: 40 additions & 0 deletions
40
apps/webapp/app/routes/projects.v3.$projectRef.runs.$runParam.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { LoaderFunctionArgs, redirect } from "@remix-run/server-runtime"; | ||
import { z } from "zod"; | ||
import { prisma } from "~/db.server"; | ||
import { requireUserId } from "~/services/session.server"; | ||
|
||
const ParamsSchema = z.object({ | ||
projectRef: z.string(), | ||
runParam: z.string(), | ||
}); | ||
|
||
export async function loader({ params, request }: LoaderFunctionArgs) { | ||
const userId = await requireUserId(request); | ||
|
||
const validatedParams = ParamsSchema.parse(params); | ||
|
||
const project = await prisma.project.findFirst({ | ||
where: { | ||
externalRef: validatedParams.projectRef, | ||
organization: { | ||
members: { | ||
some: { | ||
userId, | ||
}, | ||
}, | ||
}, | ||
}, | ||
include: { | ||
organization: true, | ||
}, | ||
}); | ||
|
||
if (!project) { | ||
return new Response("Not found", { status: 404 }); | ||
} | ||
|
||
// Redirect to the project's runs page | ||
return redirect( | ||
`/orgs/${project.organization.slug}/projects/v3/${project.slug}/runs/${validatedParams.runParam}` | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.