Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d22a460555 | |||
| 9ba2a217a4 | |||
| 39885a427f | |||
| ccb0bc510a | |||
| 56d66ee07c | |||
| 4ca8887972 | |||
| 89bffc066c | |||
| 34ca7667d3 | |||
| 3e327acc0f | |||
| 77ad4127cb | |||
| 8a5076aacf | |||
| 5399f6bfb7 | |||
| ecef199660 |
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@trigger.dev/sdk": patch
|
||||
---
|
||||
|
||||
Use global setTimeout to ensure cross-runtime support
|
||||
@@ -99,6 +99,7 @@
|
||||
"pink-pumas-rhyme",
|
||||
"plenty-ducks-beam",
|
||||
"polite-ducks-switch",
|
||||
"polite-pears-grow",
|
||||
"polite-rockets-matter",
|
||||
"poor-flowers-cross",
|
||||
"purple-garlics-shop",
|
||||
@@ -119,6 +120,7 @@
|
||||
"silly-suits-switch",
|
||||
"silver-doors-juggle",
|
||||
"six-ligers-exist",
|
||||
"six-rats-hunt",
|
||||
"sixty-insects-watch",
|
||||
"slow-buses-own",
|
||||
"slow-kiwis-hide",
|
||||
@@ -143,6 +145,7 @@
|
||||
"tender-moose-tell",
|
||||
"tender-oranges-rhyme",
|
||||
"tender-turkeys-compete",
|
||||
"thick-carrots-sneeze",
|
||||
"thin-parents-heal",
|
||||
"thirty-islands-kiss",
|
||||
"tidy-balloons-suffer",
|
||||
@@ -153,6 +156,7 @@
|
||||
"tricky-bulldogs-heal",
|
||||
"tricky-keys-attack",
|
||||
"tricky-ladybugs-unite",
|
||||
"twelve-knives-notice",
|
||||
"two-pumas-wait",
|
||||
"violet-clocks-notice",
|
||||
"warm-olives-provide",
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Improved ESM module require error detection logic
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@trigger.dev/core": patch
|
||||
"@trigger.dev/sdk": patch
|
||||
---
|
||||
|
||||
v3: Include presigned urls for downloading large payloads and outputs when using runs.retrieve
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
v3: fix missing init output in task run function when no middleware is defined
|
||||
@@ -206,6 +206,9 @@ const EnvironmentSchema = z.object({
|
||||
USAGE_OPEN_METER_BASE_URL: z.string().optional(),
|
||||
EVENT_LOOP_MONITOR_ENABLED: z.string().default("1"),
|
||||
MAXIMUM_LIVE_RELOADING_EVENTS: z.coerce.number().int().default(1000),
|
||||
MAXIMUM_TRACE_SUMMARY_VIEW_COUNT: z.coerce.number().int().default(25_000),
|
||||
TASK_PAYLOAD_OFFLOAD_THRESHOLD: z.coerce.number().int().default(524_288), // 512KB
|
||||
TASK_PAYLOAD_MAXIMUM_SIZE: z.coerce.number().int().default(3_145_728), // 3MB
|
||||
});
|
||||
|
||||
export type Environment = z.infer<typeof EnvironmentSchema>;
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import { z } from "zod";
|
||||
import {
|
||||
Direction,
|
||||
FilterableEnvironment,
|
||||
FilterableStatus,
|
||||
filterableStatuses,
|
||||
} from "~/components/runs/RunStatuses";
|
||||
import { PrismaClient, prisma } from "~/db.server";
|
||||
import { getUsername } from "~/utils/username";
|
||||
import { BasePresenter } from "./v3/basePresenter.server";
|
||||
|
||||
@@ -29,8 +27,6 @@ const DEFAULT_PAGE_SIZE = 20;
|
||||
export type RunList = Awaited<ReturnType<RunListPresenter["call"]>>;
|
||||
|
||||
export class RunListPresenter extends BasePresenter {
|
||||
|
||||
|
||||
public async call({
|
||||
userId,
|
||||
eventId,
|
||||
|
||||
@@ -1,27 +1,52 @@
|
||||
import { User } from "@trigger.dev/database";
|
||||
import { ScheduleMetadataSchema } from "@trigger.dev/core";
|
||||
import { PrismaClient, prisma } from "~/db.server";
|
||||
import { User } from "@trigger.dev/database";
|
||||
import { Organization } from "~/models/organization.server";
|
||||
import { Project } from "~/models/project.server";
|
||||
import { calculateNextScheduledEvent } from "~/services/schedules/nextScheduledEvent.server";
|
||||
import { BasePresenter } from "./v3/basePresenter.server";
|
||||
|
||||
export class ScheduledTriggersPresenter {
|
||||
#prismaClient: PrismaClient;
|
||||
|
||||
constructor(prismaClient: PrismaClient = prisma) {
|
||||
this.#prismaClient = prismaClient;
|
||||
}
|
||||
const DEFAULT_PAGE_SIZE = 20;
|
||||
|
||||
export class ScheduledTriggersPresenter extends BasePresenter {
|
||||
public async call({
|
||||
userId,
|
||||
projectSlug,
|
||||
organizationSlug,
|
||||
direction = "forward",
|
||||
pageSize = DEFAULT_PAGE_SIZE,
|
||||
cursor,
|
||||
}: {
|
||||
userId: User["id"];
|
||||
projectSlug: Project["slug"];
|
||||
organizationSlug: Organization["slug"];
|
||||
direction?: "forward" | "backward";
|
||||
pageSize?: number;
|
||||
cursor?: string;
|
||||
}) {
|
||||
const scheduled = await this.#prismaClient.scheduleSource.findMany({
|
||||
const organization = await this._replica.organization.findFirstOrThrow({
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
where: {
|
||||
slug: organizationSlug,
|
||||
members: { some: { userId } },
|
||||
},
|
||||
});
|
||||
|
||||
// Find the project scoped to the organization
|
||||
const project = await this._replica.project.findFirstOrThrow({
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
where: {
|
||||
slug: projectSlug,
|
||||
organizationId: organization.id,
|
||||
},
|
||||
});
|
||||
|
||||
const directionMultiplier = direction === "forward" ? 1 : -1;
|
||||
|
||||
const scheduled = await this._replica.scheduleSource.findMany({
|
||||
select: {
|
||||
id: true,
|
||||
key: true,
|
||||
@@ -50,23 +75,50 @@ export class ScheduledTriggersPresenter {
|
||||
},
|
||||
},
|
||||
],
|
||||
organization: {
|
||||
slug: organizationSlug,
|
||||
members: {
|
||||
some: {
|
||||
userId,
|
||||
},
|
||||
},
|
||||
},
|
||||
project: {
|
||||
slug: projectSlug,
|
||||
},
|
||||
projectId: project.id,
|
||||
},
|
||||
},
|
||||
orderBy: [{ id: "desc" }],
|
||||
//take an extra record to tell if there are more
|
||||
take: directionMultiplier * (pageSize + 1),
|
||||
//skip the cursor if there is one
|
||||
skip: cursor ? 1 : 0,
|
||||
cursor: cursor
|
||||
? {
|
||||
id: cursor,
|
||||
}
|
||||
: undefined,
|
||||
});
|
||||
|
||||
const hasMore = scheduled.length > pageSize;
|
||||
|
||||
//get cursors for next and previous pages
|
||||
let next: string | undefined;
|
||||
let previous: string | undefined;
|
||||
switch (direction) {
|
||||
case "forward":
|
||||
previous = cursor ? scheduled.at(0)?.id : undefined;
|
||||
if (hasMore) {
|
||||
next = scheduled[pageSize - 1]?.id;
|
||||
}
|
||||
break;
|
||||
case "backward":
|
||||
if (hasMore) {
|
||||
previous = scheduled[1]?.id;
|
||||
next = scheduled[pageSize]?.id;
|
||||
} else {
|
||||
next = scheduled[pageSize - 1]?.id;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
const scheduledToReturn =
|
||||
direction === "backward" && hasMore
|
||||
? scheduled.slice(1, pageSize + 1)
|
||||
: scheduled.slice(0, pageSize);
|
||||
|
||||
return {
|
||||
scheduled: scheduled.map((s) => {
|
||||
scheduled: scheduledToReturn.map((s) => {
|
||||
const schedule = ScheduleMetadataSchema.parse(s.schedule);
|
||||
const nextEventTimestamp = s.active
|
||||
? calculateNextScheduledEvent(schedule, s.lastEventTimestamp)
|
||||
@@ -78,6 +130,10 @@ export class ScheduledTriggersPresenter {
|
||||
nextEventTimestamp,
|
||||
};
|
||||
}),
|
||||
pagination: {
|
||||
next,
|
||||
previous,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
import { Prisma, TaskRunAttemptStatus, TaskRunStatus } from "@trigger.dev/database";
|
||||
import assertNever from "assert-never";
|
||||
import { AuthenticatedEnvironment } from "~/services/apiAuth.server";
|
||||
import { generatePresignedUrl } from "~/v3/r2.server";
|
||||
import { BasePresenter } from "./basePresenter.server";
|
||||
|
||||
export class ApiRetrieveRunPresenter extends BasePresenter {
|
||||
@@ -44,7 +45,9 @@ export class ApiRetrieveRunPresenter extends BasePresenter {
|
||||
}
|
||||
|
||||
let $payload: any;
|
||||
let $payloadPresignedUrl: string | undefined;
|
||||
let $output: any;
|
||||
let $outputPresignedUrl: string | undefined;
|
||||
|
||||
if (showSecretDetails) {
|
||||
const payloadPacket = await conditionallyImportPacket({
|
||||
@@ -52,7 +55,19 @@ export class ApiRetrieveRunPresenter extends BasePresenter {
|
||||
dataType: taskRun.payloadType,
|
||||
});
|
||||
|
||||
$payload = await parsePacket(payloadPacket);
|
||||
if (
|
||||
payloadPacket.dataType === "application/store" &&
|
||||
typeof payloadPacket.data === "string"
|
||||
) {
|
||||
$payloadPresignedUrl = await generatePresignedUrl(
|
||||
env.project.externalRef,
|
||||
env.slug,
|
||||
payloadPacket.data,
|
||||
"GET"
|
||||
);
|
||||
} else {
|
||||
$payload = await parsePacket(payloadPacket);
|
||||
}
|
||||
|
||||
if (taskRun.status === "COMPLETED_SUCCESSFULLY") {
|
||||
const completedAttempt = taskRun.attempts.find(
|
||||
@@ -65,7 +80,19 @@ export class ApiRetrieveRunPresenter extends BasePresenter {
|
||||
dataType: completedAttempt.outputType,
|
||||
});
|
||||
|
||||
$output = await parsePacket(outputPacket);
|
||||
if (
|
||||
outputPacket.dataType === "application/store" &&
|
||||
typeof outputPacket.data === "string"
|
||||
) {
|
||||
$outputPresignedUrl = await generatePresignedUrl(
|
||||
env.project.externalRef,
|
||||
env.slug,
|
||||
outputPacket.data,
|
||||
"GET"
|
||||
);
|
||||
} else {
|
||||
$output = await parsePacket(outputPacket);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,7 +112,9 @@ export class ApiRetrieveRunPresenter extends BasePresenter {
|
||||
? taskRun.updatedAt
|
||||
: undefined,
|
||||
payload: $payload,
|
||||
payloadPresignedUrl: $payloadPresignedUrl,
|
||||
output: $output,
|
||||
outputPresignedUrl: $outputPresignedUrl,
|
||||
isTest: taskRun.isTest,
|
||||
schedule: taskRun.schedule
|
||||
? {
|
||||
|
||||
+20
-6
@@ -2,6 +2,8 @@ import { NoSymbolIcon } from "@heroicons/react/20/solid";
|
||||
import { CheckCircleIcon, XCircleIcon } from "@heroicons/react/24/solid";
|
||||
import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { z } from "zod";
|
||||
import { ListPagination } from "~/components/ListPagination";
|
||||
import { EnvironmentLabel } from "~/components/environments/EnvironmentLabel";
|
||||
import { DateTime } from "~/components/primitives/DateTime";
|
||||
import { LabelValueStack } from "~/components/primitives/LabelValueStack";
|
||||
@@ -17,30 +19,38 @@ import {
|
||||
TableRow,
|
||||
} from "~/components/primitives/Table";
|
||||
import { TextLink } from "~/components/primitives/TextLink";
|
||||
import { useOrganization } from "~/hooks/useOrganizations";
|
||||
import { useProject } from "~/hooks/useProject";
|
||||
import { DirectionSchema } from "~/components/runs/RunStatuses";
|
||||
import { ScheduledTriggersPresenter } from "~/presenters/ScheduledTriggersPresenter.server";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
import { ProjectParamSchema, docsPath } from "~/utils/pathBuilder";
|
||||
|
||||
const SearchSchema = z.object({
|
||||
cursor: z.string().optional(),
|
||||
direction: DirectionSchema.optional(),
|
||||
});
|
||||
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const userId = await requireUserId(request);
|
||||
const { organizationSlug, projectParam } = ProjectParamSchema.parse(params);
|
||||
|
||||
const url = new URL(request.url);
|
||||
const s = Object.fromEntries(url.searchParams.entries());
|
||||
const searchParams = SearchSchema.parse(s);
|
||||
|
||||
const presenter = new ScheduledTriggersPresenter();
|
||||
const data = await presenter.call({
|
||||
userId,
|
||||
organizationSlug,
|
||||
projectSlug: projectParam,
|
||||
direction: searchParams.direction,
|
||||
cursor: searchParams.cursor,
|
||||
});
|
||||
|
||||
return typedjson(data);
|
||||
};
|
||||
|
||||
export default function Integrations() {
|
||||
const { scheduled } = useTypedLoaderData<typeof loader>();
|
||||
const organization = useOrganization();
|
||||
const project = useProject();
|
||||
export default function Route() {
|
||||
const { scheduled, pagination } = useTypedLoaderData<typeof loader>();
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -49,6 +59,10 @@ export default function Integrations() {
|
||||
expression or an interval.
|
||||
</Paragraph>
|
||||
|
||||
{scheduled.length > 0 && (
|
||||
<ListPagination list={{ pagination }} className="mt-2 justify-end" />
|
||||
)}
|
||||
|
||||
<Table containerClassName="mt-4">
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import type { ActionFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import { z } from "zod";
|
||||
import { env } from "~/env.server";
|
||||
import { authenticateApiRequest } from "~/services/apiAuth.server";
|
||||
import { logger } from "~/services/logger.server";
|
||||
import { r2 } from "~/v3/r2.server";
|
||||
import { generatePresignedUrl } from "~/v3/r2.server";
|
||||
|
||||
const ParamsSchema = z.object({
|
||||
"*": z.string(),
|
||||
@@ -26,34 +24,19 @@ export async function action({ request, params }: ActionFunctionArgs) {
|
||||
const parsedParams = ParamsSchema.parse(params);
|
||||
const filename = parsedParams["*"];
|
||||
|
||||
if (!env.OBJECT_STORE_BASE_URL) {
|
||||
return json({ error: "Object store base URL is not set" }, { status: 500 });
|
||||
}
|
||||
|
||||
if (!r2) {
|
||||
return json({ error: "Object store credentials are not set" }, { status: 500 });
|
||||
}
|
||||
|
||||
const url = new URL(env.OBJECT_STORE_BASE_URL);
|
||||
url.pathname = `/packets/${authenticationResult.environment.project.externalRef}/${authenticationResult.environment.slug}/${filename}`;
|
||||
url.searchParams.set("X-Amz-Expires", "300"); // 5 minutes
|
||||
|
||||
const signed = await r2.sign(
|
||||
new Request(url, {
|
||||
method: "PUT",
|
||||
}),
|
||||
{
|
||||
aws: { signQuery: true },
|
||||
}
|
||||
const presignedUrl = await generatePresignedUrl(
|
||||
authenticationResult.environment.project.externalRef,
|
||||
authenticationResult.environment.slug,
|
||||
filename,
|
||||
"PUT"
|
||||
);
|
||||
|
||||
logger.debug("Generated presigned URL", {
|
||||
url: signed.url,
|
||||
headers: Object.fromEntries(signed.headers),
|
||||
});
|
||||
if (!presignedUrl) {
|
||||
return json({ error: "Failed to generate presigned URL" }, { status: 500 });
|
||||
}
|
||||
|
||||
// Caller can now use this URL to upload to that object.
|
||||
return json({ presignedUrl: signed.url });
|
||||
return json({ presignedUrl });
|
||||
}
|
||||
|
||||
export async function loader({ request, params }: ActionFunctionArgs) {
|
||||
@@ -67,35 +50,17 @@ export async function loader({ request, params }: ActionFunctionArgs) {
|
||||
const parsedParams = ParamsSchema.parse(params);
|
||||
const filename = parsedParams["*"];
|
||||
|
||||
if (!env.OBJECT_STORE_BASE_URL) {
|
||||
return json({ error: "Object store base URL is not set" }, { status: 500 });
|
||||
}
|
||||
|
||||
if (!r2) {
|
||||
return json({ error: "Object store credentials are not set" }, { status: 500 });
|
||||
}
|
||||
|
||||
const url = new URL(env.OBJECT_STORE_BASE_URL);
|
||||
url.pathname = `/packets/${authenticationResult.environment.project.externalRef}/${authenticationResult.environment.slug}/${filename}`;
|
||||
url.searchParams.set("X-Amz-Expires", "300"); // 5 minutes
|
||||
|
||||
const signed = await r2.sign(
|
||||
new Request(url, {
|
||||
method: request.method,
|
||||
}),
|
||||
{
|
||||
aws: { signQuery: true },
|
||||
}
|
||||
const presignedUrl = await generatePresignedUrl(
|
||||
authenticationResult.environment.project.externalRef,
|
||||
authenticationResult.environment.slug,
|
||||
filename,
|
||||
"GET"
|
||||
);
|
||||
|
||||
logger.debug("Generated presigned URL", {
|
||||
url: signed.url,
|
||||
headers: Object.fromEntries(signed.headers),
|
||||
});
|
||||
if (!presignedUrl) {
|
||||
return json({ error: "Failed to generate presigned URL" }, { status: 500 });
|
||||
}
|
||||
|
||||
const getUrl = new URL(url.href);
|
||||
getUrl.searchParams.delete("X-Amz-Expires");
|
||||
|
||||
// Caller can now use this URL to upload to that object.
|
||||
return json({ presignedUrl: signed.url });
|
||||
// Caller can now use this URL to fetch that object.
|
||||
return json({ presignedUrl });
|
||||
}
|
||||
|
||||
+65
-59
@@ -3,6 +3,7 @@ import { PrismaClientOrTransaction, prisma } from "~/db.server";
|
||||
import { taskWithAttemptsToServerTask } from "~/models/task.server";
|
||||
import type { AuthenticatedEnvironment } from "~/services/apiAuth.server";
|
||||
import { logger } from "~/services/logger.server";
|
||||
import { startActiveSpan } from "~/v3/tracer.server";
|
||||
|
||||
export class CompleteRunTaskService {
|
||||
#prismaClient: PrismaClientOrTransaction;
|
||||
@@ -17,76 +18,81 @@ export class CompleteRunTaskService {
|
||||
id: string,
|
||||
taskBody: CompleteTaskBodyOutput
|
||||
): Promise<ServerTask | undefined> {
|
||||
const existingTask = await this.#prismaClient.task.findUnique({
|
||||
where: {
|
||||
id,
|
||||
},
|
||||
include: {
|
||||
run: true,
|
||||
attempts: {
|
||||
where: {
|
||||
status: "PENDING",
|
||||
},
|
||||
orderBy: {
|
||||
number: "desc",
|
||||
},
|
||||
take: 1,
|
||||
return startActiveSpan("CompleteRunTaskService.call", async (span) => {
|
||||
span.setAttribute("runId", runId);
|
||||
span.setAttribute("taskId", id);
|
||||
|
||||
const existingTask = await this.#prismaClient.task.findUnique({
|
||||
where: {
|
||||
id,
|
||||
},
|
||||
include: {
|
||||
run: true,
|
||||
attempts: {
|
||||
where: {
|
||||
status: "PENDING",
|
||||
},
|
||||
orderBy: {
|
||||
number: "desc",
|
||||
},
|
||||
take: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!existingTask) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (existingTask.runId !== runId) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (existingTask.run.environmentId !== environment.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
existingTask.status === "COMPLETED" ||
|
||||
existingTask.status === "ERRORED" ||
|
||||
existingTask.status === "CANCELED"
|
||||
) {
|
||||
logger.debug("Task already completed", {
|
||||
existingTask,
|
||||
});
|
||||
|
||||
return taskWithAttemptsToServerTask(existingTask);
|
||||
}
|
||||
if (!existingTask) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (existingTask.attempts.length === 1) {
|
||||
await this.#prismaClient.taskAttempt.update({
|
||||
if (existingTask.runId !== runId) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (existingTask.run.environmentId !== environment.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
existingTask.status === "COMPLETED" ||
|
||||
existingTask.status === "ERRORED" ||
|
||||
existingTask.status === "CANCELED"
|
||||
) {
|
||||
logger.debug("Task already completed", {
|
||||
taskId: id,
|
||||
});
|
||||
|
||||
return taskWithAttemptsToServerTask(existingTask);
|
||||
}
|
||||
|
||||
if (existingTask.attempts.length === 1) {
|
||||
await this.#prismaClient.taskAttempt.update({
|
||||
where: {
|
||||
id: existingTask.attempts[0].id,
|
||||
},
|
||||
data: {
|
||||
status: "COMPLETED",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const updatedTask = await this.#prismaClient.task.update({
|
||||
where: {
|
||||
id: existingTask.attempts[0].id,
|
||||
id,
|
||||
},
|
||||
data: {
|
||||
status: "COMPLETED",
|
||||
output: taskBody.output as any,
|
||||
outputIsUndefined: typeof taskBody.output === "undefined",
|
||||
completedAt: new Date(),
|
||||
outputProperties: taskBody.properties,
|
||||
},
|
||||
include: {
|
||||
attempts: true,
|
||||
run: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const updatedTask = await this.#prismaClient.task.update({
|
||||
where: {
|
||||
id,
|
||||
},
|
||||
data: {
|
||||
status: "COMPLETED",
|
||||
output: taskBody.output as any,
|
||||
outputIsUndefined: typeof taskBody.output === "undefined",
|
||||
completedAt: new Date(),
|
||||
outputProperties: taskBody.properties,
|
||||
},
|
||||
include: {
|
||||
attempts: true,
|
||||
run: true,
|
||||
},
|
||||
return taskWithAttemptsToServerTask(updatedTask);
|
||||
});
|
||||
|
||||
return taskWithAttemptsToServerTask(updatedTask);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,10 @@ import {
|
||||
import { z } from "zod";
|
||||
import type { AuthenticatedEnvironment } from "~/services/apiAuth.server";
|
||||
import { authenticateApiRequest } from "~/services/apiAuth.server";
|
||||
import { logger } from "~/services/logger.server";
|
||||
import { CompleteRunTaskService } from "./CompleteRunTaskService.server";
|
||||
import { startActiveSpan } from "~/v3/tracer.server";
|
||||
import { parseRequestJsonAsync } from "~/utils/parseRequestJson.server";
|
||||
import { FailRunTaskService } from "../api.v1.runs.$runId.tasks.$id.fail/FailRunTaskService.server";
|
||||
|
||||
const ParamsSchema = z.object({
|
||||
runId: z.string(),
|
||||
@@ -44,46 +46,51 @@ export async function action({ request, params }: ActionFunctionArgs) {
|
||||
return json({ error: "Invalid headers" }, { status: 400 });
|
||||
}
|
||||
|
||||
// Check the content size of the request and make sure it's not too large
|
||||
const contentLength = request.headers.get("content-length");
|
||||
|
||||
if (!contentLength || parseInt(contentLength) > 3 * 1024 * 1024) {
|
||||
const service = new FailRunTaskService();
|
||||
|
||||
await service.call(authenticatedEnv, runId, id, {
|
||||
error: {
|
||||
message: "Task output is too large. The limit is 3MB",
|
||||
},
|
||||
});
|
||||
|
||||
return json({ error: "Task output is too large. The limit is 3MB" }, { status: 413 });
|
||||
}
|
||||
|
||||
const { "trigger-version": triggerVersion } = headers.data;
|
||||
|
||||
// Now parse the request body
|
||||
const anyBody = await request.json();
|
||||
|
||||
logger.debug("CompleteRunTaskService.call() request body", {
|
||||
body: anyBody,
|
||||
runId,
|
||||
id,
|
||||
});
|
||||
const anyBody = await parseRequestJsonAsync(request, { runId });
|
||||
|
||||
if (triggerVersion === API_VERSIONS.SERIALIZED_TASK_OUTPUT) {
|
||||
const body = CompleteTaskBodyV2InputSchema.safeParse(anyBody);
|
||||
const body = await startActiveSpan("CompleteTaskBodyV2InputSchema.safeParse()", async () => {
|
||||
return CompleteTaskBodyV2InputSchema.safeParse(anyBody);
|
||||
});
|
||||
|
||||
if (!body.success) {
|
||||
return json({ error: "Invalid request body" }, { status: 400 });
|
||||
}
|
||||
|
||||
// Make sure the length of the output is less than 3MB
|
||||
if (body.data.output && body.data.output.length > 3 * 1024 * 1024) {
|
||||
return json({ error: "Output must be less than 3MB" }, { status: 400 });
|
||||
}
|
||||
|
||||
return await completeRunTask(authenticatedEnv, runId, id, {
|
||||
...body.data,
|
||||
output: body.data.output ? (JSON.parse(body.data.output) as any) : undefined,
|
||||
});
|
||||
} else {
|
||||
const body = CompleteTaskBodyInputSchema.safeParse(anyBody);
|
||||
const body = await startActiveSpan("CompleteTaskBodyInputSchema.safeParse()", async () => {
|
||||
return CompleteTaskBodyInputSchema.omit({ output: true }).safeParse(anyBody);
|
||||
});
|
||||
|
||||
if (!body.success) {
|
||||
return json({ error: "Invalid request body" }, { status: 400 });
|
||||
}
|
||||
|
||||
// Make sure the length of the output is less than 3MB
|
||||
if (JSON.stringify(body.data.output).length > 3 * 1024 * 1024) {
|
||||
return json({ error: "Output must be less than 3MB" }, { status: 400 });
|
||||
}
|
||||
const output = (anyBody as any).output;
|
||||
|
||||
return await completeRunTask(authenticatedEnv, runId, id, body.data);
|
||||
return await completeRunTask(authenticatedEnv, runId, id, { ...body.data, output });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,12 +105,6 @@ async function completeRunTask(
|
||||
try {
|
||||
const task = await service.call(environment, runId, id, taskBody);
|
||||
|
||||
logger.debug("CompleteRunTaskService.call() response body", {
|
||||
runId,
|
||||
id,
|
||||
task,
|
||||
});
|
||||
|
||||
if (!task) {
|
||||
return json({ message: "Task not found" }, { status: 404 });
|
||||
}
|
||||
|
||||
@@ -57,10 +57,6 @@ export class FailRunTaskService {
|
||||
existingTask.status === "ERRORED" ||
|
||||
existingTask.status === "CANCELED"
|
||||
) {
|
||||
logger.debug("Task already completed", {
|
||||
existingTask,
|
||||
});
|
||||
|
||||
return existingTask;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ import { authenticateApiRequest } from "~/services/apiAuth.server";
|
||||
import { logger } from "~/services/logger.server";
|
||||
import { RunTaskService } from "~/services/tasks/runTask.server";
|
||||
import { ChangeRequestLazyLoadedCachedTasks } from "./ChangeRequestLazyLoadedCachedTasks.server";
|
||||
import { startActiveSpan } from "~/v3/tracer.server";
|
||||
import { parseRequestJsonAsync } from "~/utils/parseRequestJson.server";
|
||||
|
||||
const ParamsSchema = z.object({
|
||||
runId: z.string(),
|
||||
@@ -17,6 +19,8 @@ const HeadersSchema = z.object({
|
||||
"x-cached-tasks-cursor": z.string().optional().nullable(),
|
||||
});
|
||||
|
||||
const BodySchema = RunTaskBodyOutputSchema.omit({ params: true });
|
||||
|
||||
export async function action({ request, params }: ActionFunctionArgs) {
|
||||
// Ensure this is a POST request
|
||||
if (request.method.toUpperCase() !== "POST") {
|
||||
@@ -44,18 +48,26 @@ export async function action({ request, params }: ActionFunctionArgs) {
|
||||
|
||||
const { runId } = ParamsSchema.parse(params);
|
||||
|
||||
const contentLength = request.headers.get("content-length");
|
||||
|
||||
if (!contentLength || parseInt(contentLength) > 3 * 1024 * 1024) {
|
||||
return json({ error: "Request body too large" }, { status: 413 });
|
||||
}
|
||||
|
||||
// Now parse the request body
|
||||
const anyBody = await request.json();
|
||||
const anyBody = await parseRequestJsonAsync(request, { runId });
|
||||
|
||||
logger.debug("RunTaskService.call() request body", {
|
||||
body: anyBody,
|
||||
runId,
|
||||
idempotencyKey,
|
||||
triggerVersion,
|
||||
cachedTasksCursor,
|
||||
});
|
||||
|
||||
const body = RunTaskBodyOutputSchema.safeParse(anyBody);
|
||||
const body = await startActiveSpan(
|
||||
"BodySchema.safeParse",
|
||||
async () => {
|
||||
return BodySchema.safeParse(anyBody);
|
||||
},
|
||||
{
|
||||
attributes: {
|
||||
runId,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (!body.success) {
|
||||
return json({ error: "Invalid request body" }, { status: 400 });
|
||||
@@ -64,12 +76,9 @@ export async function action({ request, params }: ActionFunctionArgs) {
|
||||
const service = new RunTaskService();
|
||||
|
||||
try {
|
||||
const task = await service.call(runId, idempotencyKey, body.data);
|
||||
|
||||
logger.debug("RunTaskService.call() response body", {
|
||||
runId,
|
||||
idempotencyKey,
|
||||
task,
|
||||
const task = await service.call(runId, idempotencyKey, {
|
||||
...body.data,
|
||||
params: (anyBody as any).params,
|
||||
});
|
||||
|
||||
if (!task) {
|
||||
@@ -84,7 +93,6 @@ export async function action({ request, params }: ActionFunctionArgs) {
|
||||
logger.debug(
|
||||
"RunTaskService.call() response migrating with ChangeRequestLazyLoadedCachedTasks",
|
||||
{
|
||||
responseBody,
|
||||
cachedTasksCursor,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -7,6 +7,7 @@ import { authenticateApiRequest } from "~/services/apiAuth.server";
|
||||
import { logger } from "~/services/logger.server";
|
||||
import { BatchTriggerTaskService } from "~/v3/services/batchTriggerTask.server";
|
||||
import { HeadersSchema } from "./api.v1.tasks.$taskId.trigger";
|
||||
import { env } from "~/env.server";
|
||||
|
||||
const ParamsSchema = z.object({
|
||||
taskId: z.string(),
|
||||
@@ -43,6 +44,12 @@ export async function action({ request, params }: ActionFunctionArgs) {
|
||||
|
||||
const { taskId } = ParamsSchema.parse(params);
|
||||
|
||||
const contentLength = request.headers.get("content-length");
|
||||
|
||||
if (!contentLength || parseInt(contentLength) > env.TASK_PAYLOAD_MAXIMUM_SIZE) {
|
||||
return json({ error: "Request body too large" }, { status: 413 });
|
||||
}
|
||||
|
||||
// Now parse the request body
|
||||
const anyBody = await request.json();
|
||||
|
||||
|
||||
@@ -2,9 +2,12 @@ import type { ActionFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { json } from "@remix-run/server-runtime";
|
||||
import { TriggerTaskRequestBody } from "@trigger.dev/core/v3";
|
||||
import { z } from "zod";
|
||||
import { env } from "~/env.server";
|
||||
import { authenticateApiRequest } from "~/services/apiAuth.server";
|
||||
import { logger } from "~/services/logger.server";
|
||||
import { parseRequestJsonAsync } from "~/utils/parseRequestJson.server";
|
||||
import { TriggerTaskService } from "~/v3/services/triggerTask.server";
|
||||
import { startActiveSpan } from "~/v3/tracer.server";
|
||||
|
||||
const ParamsSchema = z.object({
|
||||
taskId: z.string(),
|
||||
@@ -32,6 +35,12 @@ export async function action({ request, params }: ActionFunctionArgs) {
|
||||
return json({ error: "Invalid or Missing API key" }, { status: 401 });
|
||||
}
|
||||
|
||||
const contentLength = request.headers.get("content-length");
|
||||
|
||||
if (!contentLength || parseInt(contentLength) > env.TASK_PAYLOAD_MAXIMUM_SIZE) {
|
||||
return json({ error: "Request body too large" }, { status: 413 });
|
||||
}
|
||||
|
||||
const rawHeaders = Object.fromEntries(request.headers);
|
||||
|
||||
const headers = HeadersSchema.safeParse(rawHeaders);
|
||||
@@ -52,9 +61,11 @@ export async function action({ request, params }: ActionFunctionArgs) {
|
||||
const { taskId } = ParamsSchema.parse(params);
|
||||
|
||||
// Now parse the request body
|
||||
const anyBody = await request.json();
|
||||
const anyBody = await parseRequestJsonAsync(request, { taskId });
|
||||
|
||||
const body = TriggerTaskRequestBody.safeParse(anyBody);
|
||||
const body = await startActiveSpan("TriggerTaskRequestBody.safeParse()", async (span) => {
|
||||
return TriggerTaskRequestBody.safeParse(anyBody);
|
||||
});
|
||||
|
||||
if (!body.success) {
|
||||
return json({ error: "Invalid request body" }, { status: 400 });
|
||||
@@ -76,17 +87,23 @@ export async function action({ request, params }: ActionFunctionArgs) {
|
||||
idempotencyKey,
|
||||
triggerVersion,
|
||||
headers: Object.fromEntries(request.headers),
|
||||
body: body.data,
|
||||
options: body.data.options,
|
||||
isFromWorker,
|
||||
traceContext,
|
||||
});
|
||||
|
||||
const run = await service.call(taskId, authenticationResult.environment, body.data, {
|
||||
idempotencyKey: idempotencyKey ?? undefined,
|
||||
triggerVersion: triggerVersion ?? undefined,
|
||||
traceContext,
|
||||
spanParentAsLink: spanParentAsLink === 1,
|
||||
});
|
||||
const run = await service.call(
|
||||
taskId,
|
||||
authenticationResult.environment,
|
||||
{ ...body.data },
|
||||
// { ...body.data, payload: (anyBody as any).payload },
|
||||
{
|
||||
idempotencyKey: idempotencyKey ?? undefined,
|
||||
triggerVersion: triggerVersion ?? undefined,
|
||||
traceContext,
|
||||
spanParentAsLink: spanParentAsLink === 1,
|
||||
}
|
||||
);
|
||||
|
||||
if (!run) {
|
||||
return json({ error: "Task not found" }, { status: 404 });
|
||||
|
||||
+25
-1
@@ -33,7 +33,13 @@ import { redirectWithErrorMessage } from "~/models/message.server";
|
||||
import { Span, SpanPresenter } from "~/presenters/v3/SpanPresenter.server";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
import { cn } from "~/utils/cn";
|
||||
import { v3RunPath, v3RunSpanPath, v3SpanParamsSchema, v3TraceSpanPath } from "~/utils/pathBuilder";
|
||||
import {
|
||||
v3RunDownloadLogsPath,
|
||||
v3RunPath,
|
||||
v3RunSpanPath,
|
||||
v3SpanParamsSchema,
|
||||
v3TraceSpanPath,
|
||||
} from "~/utils/pathBuilder";
|
||||
import { SpanLink } from "~/v3/eventRepository.server";
|
||||
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
@@ -256,6 +262,15 @@ function RunActionButtons({ span }: { span: Span }) {
|
||||
if (span.isPartial) {
|
||||
return (
|
||||
<Dialog>
|
||||
<LinkButton
|
||||
to={v3RunDownloadLogsPath({ friendlyId: runParam })}
|
||||
LeadingIcon={CloudArrowDownIcon}
|
||||
variant="tertiary/medium"
|
||||
target="_blank"
|
||||
download
|
||||
>
|
||||
Download logs
|
||||
</LinkButton>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="danger/medium" LeadingIcon={StopCircleIcon}>
|
||||
Cancel run
|
||||
@@ -276,6 +291,15 @@ function RunActionButtons({ span }: { span: Span }) {
|
||||
|
||||
return (
|
||||
<Dialog>
|
||||
<LinkButton
|
||||
to={v3RunDownloadLogsPath({ friendlyId: runParam })}
|
||||
LeadingIcon={CloudArrowDownIcon}
|
||||
variant="tertiary/medium"
|
||||
target="_blank"
|
||||
download
|
||||
>
|
||||
Download logs
|
||||
</LinkButton>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="tertiary/medium" LeadingIcon={ArrowPathIcon}>
|
||||
Replay run
|
||||
|
||||
@@ -2,9 +2,8 @@ import { LoaderFunctionArgs } from "@remix-run/node";
|
||||
import { basename } from "node:path";
|
||||
import { z } from "zod";
|
||||
import { prisma } from "~/db.server";
|
||||
import { env } from "~/env.server";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
import { r2 } from "~/v3/r2.server";
|
||||
import { generatePresignedRequest } from "~/v3/r2.server";
|
||||
|
||||
const ParamSchema = z.object({
|
||||
environmentId: z.string(),
|
||||
@@ -35,27 +34,17 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
|
||||
return new Response("Not found", { status: 404 });
|
||||
}
|
||||
|
||||
if (!env.OBJECT_STORE_BASE_URL) {
|
||||
return new Response("Object store base URL is not set", { status: 500 });
|
||||
}
|
||||
|
||||
if (!r2) {
|
||||
return new Response("Object store credentials are not set", { status: 500 });
|
||||
}
|
||||
|
||||
const url = new URL(env.OBJECT_STORE_BASE_URL);
|
||||
url.pathname = `/packets/${environment.project.externalRef}/${environment.slug}/${filename}`;
|
||||
url.searchParams.set("X-Amz-Expires", "30"); // 30 seconds
|
||||
|
||||
const signed = await r2.sign(
|
||||
new Request(url, {
|
||||
method: "GET",
|
||||
}),
|
||||
{
|
||||
aws: { signQuery: true },
|
||||
}
|
||||
const signed = await generatePresignedRequest(
|
||||
environment.project.externalRef,
|
||||
environment.slug,
|
||||
filename,
|
||||
"GET"
|
||||
);
|
||||
|
||||
if (!signed) {
|
||||
return new Response("Failed to generate presigned URL", { status: 500 });
|
||||
}
|
||||
|
||||
const response = await fetch(signed.url, {
|
||||
headers: signed.headers,
|
||||
});
|
||||
@@ -64,7 +53,7 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
|
||||
status: 200,
|
||||
headers: {
|
||||
"Content-Type": "application/octet-stream",
|
||||
"Content-Disposition": `attachment; filename="${basename(url.pathname)}"`,
|
||||
"Content-Disposition": `attachment; filename="${basename(filename)}"`,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
import { LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { prisma } from "~/db.server";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
import { v3RunParamsSchema } from "~/utils/pathBuilder";
|
||||
import {
|
||||
PreparedEvent,
|
||||
RunPreparedEvent,
|
||||
eventRepository,
|
||||
getDateFromNanoseconds,
|
||||
} from "~/v3/eventRepository.server";
|
||||
import { createGzip } from "zlib";
|
||||
import { Readable } from "stream";
|
||||
import { formatDurationMilliseconds } from "@trigger.dev/core/v3/utils/durations";
|
||||
|
||||
export async function loader({ params, request }: LoaderFunctionArgs) {
|
||||
const userId = await requireUserId(request);
|
||||
const parsedParams = v3RunParamsSchema.pick({ runParam: true }).parse(params);
|
||||
|
||||
const run = await prisma.taskRun.findFirst({
|
||||
where: {
|
||||
friendlyId: parsedParams.runParam,
|
||||
project: {
|
||||
organization: {
|
||||
members: {
|
||||
some: {
|
||||
userId,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!run) {
|
||||
return new Response("Not found", { status: 404 });
|
||||
}
|
||||
|
||||
const runEvents = await eventRepository.getRunEvents(run.friendlyId);
|
||||
|
||||
// Create a Readable stream from the runEvents array
|
||||
const readable = new Readable({
|
||||
read() {
|
||||
runEvents.forEach((event) => {
|
||||
try {
|
||||
this.push(formatRunEvent(event) + "\n");
|
||||
} catch {}
|
||||
});
|
||||
this.push(null); // End of stream
|
||||
},
|
||||
});
|
||||
|
||||
// Create a gzip transform stream
|
||||
const gzip = createGzip();
|
||||
|
||||
// Pipe the readable stream into the gzip stream
|
||||
const compressedStream = readable.pipe(gzip);
|
||||
|
||||
// Return the response with the compressed stream
|
||||
return new Response(compressedStream as any, {
|
||||
status: 200,
|
||||
headers: {
|
||||
"Content-Type": "application/octet-stream",
|
||||
"Content-Disposition": `attachment; filename="${parsedParams.runParam}.log"`,
|
||||
"Content-Encoding": "gzip",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function formatRunEvent(event: RunPreparedEvent): string {
|
||||
const entries = [];
|
||||
const parts: string[] = [];
|
||||
|
||||
parts.push(getDateFromNanoseconds(event.startTime).toISOString());
|
||||
|
||||
if (event.taskSlug) {
|
||||
parts.push(event.taskSlug);
|
||||
}
|
||||
|
||||
parts.push(event.level);
|
||||
parts.push(event.message);
|
||||
|
||||
if (event.level === "TRACE") {
|
||||
parts.push(`(${formatDurationMilliseconds(event.duration / 1_000_000)})`);
|
||||
}
|
||||
|
||||
entries.push(parts.join(" "));
|
||||
|
||||
if (event.events) {
|
||||
for (const subEvent of event.events) {
|
||||
if (subEvent.name === "exception") {
|
||||
const subEventParts: string[] = [];
|
||||
|
||||
subEventParts.push(subEvent.time as unknown as string);
|
||||
|
||||
if (event.taskSlug) {
|
||||
subEventParts.push(event.taskSlug);
|
||||
}
|
||||
|
||||
subEventParts.push(subEvent.name);
|
||||
subEventParts.push((subEvent.properties as any).exception.message);
|
||||
|
||||
if ((subEvent.properties as any).exception.stack) {
|
||||
subEventParts.push((subEvent.properties as any).exception.stack);
|
||||
}
|
||||
|
||||
entries.push(subEventParts.join(" "));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return entries.join("\n");
|
||||
}
|
||||
@@ -136,7 +136,7 @@ export class EndpointApi {
|
||||
};
|
||||
}
|
||||
|
||||
async executeJobRequest(options: RunJobBody) {
|
||||
async executeJobRequest(options: RunJobBody, timeoutInMs?: number) {
|
||||
const startTimeInMs = performance.now();
|
||||
|
||||
const response = await safeFetch(this.url, {
|
||||
@@ -147,8 +147,18 @@ export class EndpointApi {
|
||||
"x-trigger-action": "EXECUTE_JOB",
|
||||
},
|
||||
body: JSON.stringify(options),
|
||||
signal: timeoutInMs ? AbortSignal.timeout(timeoutInMs) : undefined,
|
||||
});
|
||||
|
||||
if (response) {
|
||||
logger.debug("executeJobRequest() response from endpoint", {
|
||||
status: response.status,
|
||||
headers: Object.fromEntries(response.headers.entries()),
|
||||
});
|
||||
} else {
|
||||
logger.debug("executeJobRequest() no response from endpoint");
|
||||
}
|
||||
|
||||
return {
|
||||
response,
|
||||
parser: RunJobResponseSchema,
|
||||
@@ -434,7 +444,10 @@ async function safeFetch(url: string, options: RequestInit) {
|
||||
} catch (error) {
|
||||
logger.debug("Error while trying to connect to endpoint", {
|
||||
url,
|
||||
error,
|
||||
error:
|
||||
error instanceof Error
|
||||
? { name: error.name, message: error.message, stack: error.stack }
|
||||
: String(error),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,7 +269,10 @@ export class PerformRunExecutionV3Service {
|
||||
|
||||
// TODO: add the ability to abort the execution from any server using Redis pub/sub
|
||||
const { response, parser, errorParser, headersParser, durationInMs } =
|
||||
await client.executeJobRequest(executionBody);
|
||||
await client.executeJobRequest(
|
||||
executionBody,
|
||||
run.environment.type === "DEVELOPMENT" ? 60_000 * 5 : undefined
|
||||
);
|
||||
|
||||
await createExecutionEvent({
|
||||
eventType: "finish",
|
||||
@@ -929,6 +932,25 @@ export class PerformRunExecutionV3Service {
|
||||
executionCount: number = 1
|
||||
) {
|
||||
await $transaction(this.#prismaClient, async (tx) => {
|
||||
const service = new CompleteRunTaskService(tx);
|
||||
|
||||
const task = await service.call(run.environment, run.id, data.id, {
|
||||
properties: data.properties,
|
||||
output: data.output ? (JSON.parse(data.output) as any) : undefined,
|
||||
});
|
||||
|
||||
if (!task || task.status === "ERRORED") {
|
||||
return await this.#failRunExecution(
|
||||
tx,
|
||||
run,
|
||||
{
|
||||
message: task ? `Task '${task.name}' failed to complete` : "Task failed to complete",
|
||||
},
|
||||
"FAILURE",
|
||||
durationInMs
|
||||
);
|
||||
}
|
||||
|
||||
await tx.jobRun.update({
|
||||
where: {
|
||||
id: run.id,
|
||||
@@ -958,13 +980,6 @@ export class PerformRunExecutionV3Service {
|
||||
},
|
||||
});
|
||||
|
||||
const service = new CompleteRunTaskService(tx);
|
||||
|
||||
await service.call(run.environment, run.id, data.id, {
|
||||
properties: data.properties,
|
||||
output: data.output ? (JSON.parse(data.output) as any) : undefined,
|
||||
});
|
||||
|
||||
await ResumeRunService.enqueue(run, tx);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { taskWithAttemptsToServerTask } from "~/models/task.server";
|
||||
import { generateSecret } from "~/services/sources/utils.server";
|
||||
import { ulid } from "~/services/ulid.server";
|
||||
import { taskOperationWorker, workerQueue } from "~/services/worker.server";
|
||||
import { startActiveSpan } from "~/v3/tracer.server";
|
||||
|
||||
export class RunTaskService {
|
||||
#prismaClient: PrismaClient;
|
||||
@@ -19,142 +20,154 @@ export class RunTaskService {
|
||||
idempotencyKey: string,
|
||||
taskBody: RunTaskBodyOutput
|
||||
): Promise<ServerTask | undefined> {
|
||||
const delayUntilInFuture = taskBody.delayUntil
|
||||
? taskBody.delayUntil.getTime() > Date.now()
|
||||
: false;
|
||||
const callbackEnabled = taskBody.callback?.enabled ?? false;
|
||||
return startActiveSpan("RunTaskService.call", async (span) => {
|
||||
span.setAttribute("runId", runId);
|
||||
|
||||
// First
|
||||
const existingTask = await this.#handleExistingTask(
|
||||
runId,
|
||||
idempotencyKey,
|
||||
taskBody,
|
||||
delayUntilInFuture,
|
||||
callbackEnabled
|
||||
);
|
||||
const delayUntilInFuture = taskBody.delayUntil
|
||||
? taskBody.delayUntil.getTime() > Date.now()
|
||||
: false;
|
||||
const callbackEnabled = taskBody.callback?.enabled ?? false;
|
||||
|
||||
if (existingTask) {
|
||||
return taskWithAttemptsToServerTask(existingTask);
|
||||
}
|
||||
// First
|
||||
const existingTask = await this.#handleExistingTask(
|
||||
runId,
|
||||
idempotencyKey,
|
||||
taskBody,
|
||||
delayUntilInFuture,
|
||||
callbackEnabled
|
||||
);
|
||||
|
||||
const run = await this.#prismaClient.jobRun.findUnique({
|
||||
where: {
|
||||
id: runId,
|
||||
},
|
||||
select: {
|
||||
status: true,
|
||||
forceYieldImmediately: true,
|
||||
},
|
||||
});
|
||||
if (existingTask) {
|
||||
span.setAttribute("taskId", existingTask.id);
|
||||
|
||||
if (!run) throw new Error("Run not found");
|
||||
|
||||
const runConnection = taskBody.connectionKey
|
||||
? await this.#prismaClient.runConnection.findUnique({
|
||||
where: {
|
||||
runId_key: {
|
||||
runId,
|
||||
key: taskBody.connectionKey,
|
||||
},
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
})
|
||||
: undefined;
|
||||
|
||||
const results = await $transaction(this.#prismaClient, async (tx) => {
|
||||
// If task.delayUntil is set and is in the future, we'll set the task's status to "WAITING", else set it to RUNNING
|
||||
let status: TaskStatus;
|
||||
|
||||
if (run.status === "CANCELED") {
|
||||
status = "CANCELED";
|
||||
} else {
|
||||
status =
|
||||
delayUntilInFuture || callbackEnabled
|
||||
? "WAITING"
|
||||
: taskBody.noop
|
||||
? "COMPLETED"
|
||||
: "RUNNING";
|
||||
return taskWithAttemptsToServerTask(existingTask);
|
||||
}
|
||||
|
||||
const taskId = ulid();
|
||||
const callbackUrl = callbackEnabled
|
||||
? `${env.APP_ORIGIN}/api/v1/tasks/${taskId}/callback/${generateSecret(12)}`
|
||||
const run = await this.#prismaClient.jobRun.findUnique({
|
||||
where: {
|
||||
id: runId,
|
||||
},
|
||||
select: {
|
||||
status: true,
|
||||
forceYieldImmediately: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!run) throw new Error("Run not found");
|
||||
|
||||
const runConnection = taskBody.connectionKey
|
||||
? await this.#prismaClient.runConnection.findUnique({
|
||||
where: {
|
||||
runId_key: {
|
||||
runId,
|
||||
key: taskBody.connectionKey,
|
||||
},
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
})
|
||||
: undefined;
|
||||
|
||||
const task = await tx.task.create({
|
||||
data: {
|
||||
id: taskId,
|
||||
idempotencyKey,
|
||||
displayKey: taskBody.displayKey,
|
||||
runConnectionId: runConnection ? runConnection.id : undefined,
|
||||
icon: taskBody.icon,
|
||||
runId,
|
||||
parentId: taskBody.parentId,
|
||||
name: taskBody.name ?? "Task",
|
||||
description: taskBody.description,
|
||||
status,
|
||||
startedAt: new Date(),
|
||||
completedAt: status === "COMPLETED" || status === "CANCELED" ? new Date() : undefined,
|
||||
noop: taskBody.noop,
|
||||
delayUntil: taskBody.delayUntil,
|
||||
params: taskBody.params ?? undefined,
|
||||
properties: this.#filterProperties(taskBody.properties) ?? undefined,
|
||||
redact: taskBody.redact ?? undefined,
|
||||
operation: taskBody.operation,
|
||||
callbackUrl,
|
||||
style: taskBody.style ?? { style: "normal" },
|
||||
childExecutionMode: taskBody.parallel ? "PARALLEL" : "SEQUENTIAL",
|
||||
},
|
||||
});
|
||||
const results = await $transaction(
|
||||
this.#prismaClient,
|
||||
async (tx) => {
|
||||
// If task.delayUntil is set and is in the future, we'll set the task's status to "WAITING", else set it to RUNNING
|
||||
let status: TaskStatus;
|
||||
|
||||
const taskAttempt = await tx.taskAttempt.create({
|
||||
data: {
|
||||
number: 1,
|
||||
taskId: task.id,
|
||||
status: "PENDING",
|
||||
},
|
||||
});
|
||||
if (run.status === "CANCELED") {
|
||||
status = "CANCELED";
|
||||
} else {
|
||||
status =
|
||||
delayUntilInFuture || callbackEnabled
|
||||
? "WAITING"
|
||||
: taskBody.noop
|
||||
? "COMPLETED"
|
||||
: "RUNNING";
|
||||
}
|
||||
|
||||
if (task.status === "RUNNING" && typeof taskBody.operation === "string") {
|
||||
// We need to schedule the operation
|
||||
await taskOperationWorker.enqueue(
|
||||
"performTaskOperation",
|
||||
{
|
||||
id: task.id,
|
||||
},
|
||||
{ tx, runAt: task.delayUntil ?? undefined, jobKey: `operation:${task.id}` }
|
||||
);
|
||||
} else if (task.status === "WAITING" && callbackUrl && taskBody.callback) {
|
||||
if (taskBody.callback.timeoutInSeconds > 0) {
|
||||
// We need to schedule the callback timeout
|
||||
await workerQueue.enqueue(
|
||||
"processCallbackTimeout",
|
||||
{
|
||||
id: task.id,
|
||||
const taskId = ulid();
|
||||
const callbackUrl = callbackEnabled
|
||||
? `${env.APP_ORIGIN}/api/v1/tasks/${taskId}/callback/${generateSecret(12)}`
|
||||
: undefined;
|
||||
|
||||
const task = await tx.task.create({
|
||||
data: {
|
||||
id: taskId,
|
||||
idempotencyKey,
|
||||
displayKey: taskBody.displayKey,
|
||||
runConnectionId: runConnection ? runConnection.id : undefined,
|
||||
icon: taskBody.icon,
|
||||
runId,
|
||||
parentId: taskBody.parentId,
|
||||
name: taskBody.name ?? "Task",
|
||||
description: taskBody.description,
|
||||
status,
|
||||
startedAt: new Date(),
|
||||
completedAt: status === "COMPLETED" || status === "CANCELED" ? new Date() : undefined,
|
||||
noop: taskBody.noop,
|
||||
delayUntil: taskBody.delayUntil,
|
||||
params: taskBody.params ?? undefined,
|
||||
properties: this.#filterProperties(taskBody.properties) ?? undefined,
|
||||
redact: taskBody.redact ?? undefined,
|
||||
operation: taskBody.operation,
|
||||
callbackUrl,
|
||||
style: taskBody.style ?? { style: "normal" },
|
||||
childExecutionMode: taskBody.parallel ? "PARALLEL" : "SEQUENTIAL",
|
||||
},
|
||||
{
|
||||
tx,
|
||||
runAt: new Date(Date.now() + taskBody.callback.timeoutInSeconds * 1000),
|
||||
jobKey: `process-callback:${task.id}`,
|
||||
});
|
||||
|
||||
span.setAttribute("taskId", task.id);
|
||||
|
||||
const taskAttempt = await tx.taskAttempt.create({
|
||||
data: {
|
||||
number: 1,
|
||||
taskId: task.id,
|
||||
status: "PENDING",
|
||||
},
|
||||
});
|
||||
|
||||
if (task.status === "RUNNING" && typeof taskBody.operation === "string") {
|
||||
// We need to schedule the operation
|
||||
await taskOperationWorker.enqueue(
|
||||
"performTaskOperation",
|
||||
{
|
||||
id: task.id,
|
||||
},
|
||||
{ tx, runAt: task.delayUntil ?? undefined, jobKey: `operation:${task.id}` }
|
||||
);
|
||||
} else if (task.status === "WAITING" && callbackUrl && taskBody.callback) {
|
||||
if (taskBody.callback.timeoutInSeconds > 0) {
|
||||
// We need to schedule the callback timeout
|
||||
await workerQueue.enqueue(
|
||||
"processCallbackTimeout",
|
||||
{
|
||||
id: task.id,
|
||||
},
|
||||
{
|
||||
tx,
|
||||
runAt: new Date(Date.now() + taskBody.callback.timeoutInSeconds * 1000),
|
||||
jobKey: `process-callback:${task.id}`,
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return { task, taskAttempt };
|
||||
},
|
||||
{ timeout: 10000 }
|
||||
);
|
||||
|
||||
if (!results) {
|
||||
return;
|
||||
}
|
||||
|
||||
return { task, taskAttempt };
|
||||
const { task, taskAttempt } = results;
|
||||
|
||||
return task
|
||||
? taskWithAttemptsToServerTask({ ...task, attempts: [taskAttempt], run })
|
||||
: undefined;
|
||||
});
|
||||
|
||||
if (!results) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { task, taskAttempt } = results;
|
||||
|
||||
return task
|
||||
? taskWithAttemptsToServerTask({ ...task, attempts: [taskAttempt], run })
|
||||
: undefined;
|
||||
}
|
||||
|
||||
async #handleExistingTask(
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import { Attributes } from "@opentelemetry/api";
|
||||
import { startActiveSpan } from "~/v3/tracer.server";
|
||||
|
||||
export async function parseRequestJsonAsync(
|
||||
request: Request,
|
||||
attributes?: Attributes
|
||||
): Promise<unknown> {
|
||||
return await startActiveSpan(
|
||||
"parseRequestJsonAsync()",
|
||||
async (span) => {
|
||||
span.setAttribute("content-length", parseInt(request.headers.get("content-length") ?? "0"));
|
||||
span.setAttribute("content-type", request.headers.get("content-type") ?? "application/json");
|
||||
span.setAttribute("experiment.async", false);
|
||||
|
||||
const rawText = await startActiveSpan("request.text()", async () => {
|
||||
return await request.text();
|
||||
});
|
||||
|
||||
if (rawText.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
return JSON.parse(rawText);
|
||||
},
|
||||
{
|
||||
attributes,
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -375,6 +375,10 @@ export function v3RunPath(organization: OrgForPath, project: ProjectForPath, run
|
||||
return `${v3RunsPath(organization, project)}/${run.friendlyId}`;
|
||||
}
|
||||
|
||||
export function v3RunDownloadLogsPath(run: v3RunForPath) {
|
||||
return `/resources/runs/${run.friendlyId}/logs/download`;
|
||||
}
|
||||
|
||||
export function v3RunSpanPath(
|
||||
organization: OrgForPath,
|
||||
project: ProjectForPath,
|
||||
|
||||
@@ -129,6 +129,10 @@ export type PreparedEvent = Omit<QueriedEvent, "events" | "style" | "duration">
|
||||
style: TaskEventStyle;
|
||||
};
|
||||
|
||||
export type RunPreparedEvent = PreparedEvent & {
|
||||
taskSlug?: string;
|
||||
};
|
||||
|
||||
export type SpanLink =
|
||||
| {
|
||||
type: "run";
|
||||
@@ -400,13 +404,19 @@ export class EventRepository {
|
||||
orderBy: {
|
||||
startTime: "asc",
|
||||
},
|
||||
take: env.MAXIMUM_TRACE_SUMMARY_VIEW_COUNT,
|
||||
});
|
||||
|
||||
let preparedEvents: Array<PreparedEvent> = [];
|
||||
let rootSpanId: string | undefined;
|
||||
const eventsBySpanId = new Map<string, PreparedEvent>();
|
||||
|
||||
for (const event of events) {
|
||||
preparedEvents.push(prepareEvent(event));
|
||||
|
||||
if (!rootSpanId && !event.parentId) {
|
||||
rootSpanId = event.spanId;
|
||||
}
|
||||
}
|
||||
|
||||
for (const event of preparedEvents) {
|
||||
@@ -424,6 +434,8 @@ export class EventRepository {
|
||||
|
||||
preparedEvents = Array.from(eventsBySpanId.values());
|
||||
|
||||
const spansBySpanId = new Map<string, SpanSummary>();
|
||||
|
||||
const spans = preparedEvents.map((event) => {
|
||||
const ancestorCancelled = isAncestorCancelled(eventsBySpanId, event.spanId);
|
||||
const duration = calculateDurationIfAncestorIsCancelled(
|
||||
@@ -432,7 +444,7 @@ export class EventRepository {
|
||||
event.duration
|
||||
);
|
||||
|
||||
return {
|
||||
const span = {
|
||||
recordId: event.id,
|
||||
id: event.spanId,
|
||||
parentId: event.parentId ?? undefined,
|
||||
@@ -451,14 +463,17 @@ export class EventRepository {
|
||||
environmentType: event.environmentType,
|
||||
},
|
||||
};
|
||||
|
||||
spansBySpanId.set(event.spanId, span);
|
||||
|
||||
return span;
|
||||
});
|
||||
|
||||
const rootSpanId = events.find((event) => !event.parentId);
|
||||
if (!rootSpanId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const rootSpan = spans.find((span) => span.id === rootSpanId.spanId);
|
||||
const rootSpan = spansBySpanId.get(rootSpanId);
|
||||
|
||||
if (!rootSpan) {
|
||||
return;
|
||||
@@ -471,85 +486,259 @@ export class EventRepository {
|
||||
});
|
||||
}
|
||||
|
||||
public async getRunEvents(runId: string): Promise<RunPreparedEvent[]> {
|
||||
return await startActiveSpan("getRunEvents", async (span) => {
|
||||
const events = await this.readReplica.taskEvent.findMany({
|
||||
select: {
|
||||
id: true,
|
||||
spanId: true,
|
||||
parentId: true,
|
||||
runId: true,
|
||||
idempotencyKey: true,
|
||||
message: true,
|
||||
style: true,
|
||||
startTime: true,
|
||||
duration: true,
|
||||
isError: true,
|
||||
isPartial: true,
|
||||
isCancelled: true,
|
||||
level: true,
|
||||
events: true,
|
||||
environmentType: true,
|
||||
taskSlug: true,
|
||||
},
|
||||
where: {
|
||||
runId,
|
||||
isPartial: false,
|
||||
},
|
||||
orderBy: {
|
||||
startTime: "asc",
|
||||
},
|
||||
});
|
||||
|
||||
let preparedEvents: Array<PreparedEvent> = [];
|
||||
|
||||
for (const event of events) {
|
||||
preparedEvents.push(prepareEvent(event));
|
||||
}
|
||||
|
||||
return preparedEvents;
|
||||
});
|
||||
}
|
||||
|
||||
// A Span can be cancelled if it is partial and has a parent that is cancelled
|
||||
// And a span's duration, if it is partial and has a cancelled parent, is the time between the start of the span and the time of the cancellation event of the parent
|
||||
public async getSpan(spanId: string, traceId: string) {
|
||||
const traceSummary = await this.getTraceSummary(traceId);
|
||||
return await startActiveSpan("getSpan", async (s) => {
|
||||
const spanEvent = await this.#getSpanEvent(spanId);
|
||||
|
||||
const span = traceSummary?.spans.find((span) => span.id === spanId);
|
||||
if (!spanEvent) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!span) {
|
||||
return;
|
||||
}
|
||||
const preparedEvent = prepareEvent(spanEvent);
|
||||
|
||||
const fullEvent = await this.readReplica.taskEvent.findUnique({
|
||||
where: {
|
||||
id: span.recordId,
|
||||
},
|
||||
});
|
||||
const span = await this.#createSpanFromEvent(preparedEvent);
|
||||
|
||||
if (!fullEvent) {
|
||||
return;
|
||||
}
|
||||
const output = rehydrateJson(spanEvent.output);
|
||||
const payload = rehydrateJson(spanEvent.payload);
|
||||
|
||||
const output = rehydrateJson(fullEvent.output);
|
||||
const payload = rehydrateJson(fullEvent.payload);
|
||||
const show = rehydrateShow(spanEvent.properties);
|
||||
|
||||
const show = rehydrateShow(fullEvent.properties);
|
||||
const properties = sanitizedAttributes(spanEvent.properties);
|
||||
|
||||
const properties = sanitizedAttributes(fullEvent.properties);
|
||||
const messagingEvent = SpanMessagingEvent.optional().safeParse(
|
||||
(properties as any)?.messaging
|
||||
);
|
||||
|
||||
const messagingEvent = SpanMessagingEvent.optional().safeParse((properties as any)?.messaging);
|
||||
const links: SpanLink[] = [];
|
||||
|
||||
const links: SpanLink[] = [];
|
||||
|
||||
if (messagingEvent.success && messagingEvent.data) {
|
||||
if (messagingEvent.data.message && "id" in messagingEvent.data.message) {
|
||||
if (messagingEvent.data.message.id.startsWith("run_")) {
|
||||
links.push({
|
||||
type: "run",
|
||||
icon: "runs",
|
||||
title: `Run ${messagingEvent.data.message.id}`,
|
||||
runId: messagingEvent.data.message.id,
|
||||
});
|
||||
if (messagingEvent.success && messagingEvent.data) {
|
||||
if (messagingEvent.data.message && "id" in messagingEvent.data.message) {
|
||||
if (messagingEvent.data.message.id.startsWith("run_")) {
|
||||
links.push({
|
||||
type: "run",
|
||||
icon: "runs",
|
||||
title: `Run ${messagingEvent.data.message.id}`,
|
||||
runId: messagingEvent.data.message.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const backLinks = fullEvent.links as any as Link[] | undefined;
|
||||
const backLinks = spanEvent.links as any as Link[] | undefined;
|
||||
|
||||
if (backLinks && backLinks.length > 0) {
|
||||
backLinks.forEach((l) => {
|
||||
const title = String(
|
||||
l.attributes?.[SemanticInternalAttributes.LINK_TITLE] ?? "Triggered by"
|
||||
);
|
||||
if (backLinks && backLinks.length > 0) {
|
||||
backLinks.forEach((l) => {
|
||||
const title = String(
|
||||
l.attributes?.[SemanticInternalAttributes.LINK_TITLE] ?? "Triggered by"
|
||||
);
|
||||
|
||||
links.push({
|
||||
type: "span",
|
||||
icon: "trigger",
|
||||
title,
|
||||
traceId: l.context.traceId,
|
||||
spanId: l.context.spanId,
|
||||
links.push({
|
||||
type: "span",
|
||||
icon: "trigger",
|
||||
title,
|
||||
traceId: l.context.traceId,
|
||||
spanId: l.context.spanId,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const spanEvents = transformEvents(
|
||||
preparedEvent.events,
|
||||
spanEvent.metadata as Attributes,
|
||||
spanEvent.environmentType === "DEVELOPMENT"
|
||||
);
|
||||
|
||||
return {
|
||||
...spanEvent,
|
||||
...span.data,
|
||||
payload,
|
||||
output,
|
||||
properties,
|
||||
events: spanEvents,
|
||||
show,
|
||||
links,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
async #createSpanFromEvent(event: PreparedEvent) {
|
||||
return await startActiveSpan("createSpanFromEvent", async (s) => {
|
||||
let ancestorCancelled = false;
|
||||
let duration = event.duration;
|
||||
|
||||
if (!event.isCancelled && event.isPartial) {
|
||||
await this.#walkSpanAncestors(event, (ancestorEvent, level) => {
|
||||
if (level >= 8) {
|
||||
return { stop: true };
|
||||
}
|
||||
|
||||
if (ancestorEvent.isCancelled) {
|
||||
ancestorCancelled = true;
|
||||
|
||||
// We need to get the cancellation time from the cancellation span event
|
||||
const cancellationEvent = ancestorEvent.events.find(
|
||||
(event) => event.name === "cancellation"
|
||||
);
|
||||
|
||||
if (cancellationEvent) {
|
||||
duration = calculateDurationFromStart(event.startTime, cancellationEvent.time);
|
||||
}
|
||||
|
||||
return { stop: true };
|
||||
}
|
||||
|
||||
return { stop: false };
|
||||
});
|
||||
}
|
||||
|
||||
const span = {
|
||||
recordId: event.id,
|
||||
id: event.spanId,
|
||||
parentId: event.parentId ?? undefined,
|
||||
runId: event.runId,
|
||||
idempotencyKey: event.idempotencyKey,
|
||||
data: {
|
||||
message: event.message,
|
||||
style: event.style,
|
||||
duration,
|
||||
isError: event.isError,
|
||||
isPartial: ancestorCancelled ? false : event.isPartial,
|
||||
isCancelled: event.isCancelled === true ? true : event.isPartial && ancestorCancelled,
|
||||
startTime: getDateFromNanoseconds(event.startTime),
|
||||
level: event.level,
|
||||
events: event.events,
|
||||
environmentType: event.environmentType,
|
||||
},
|
||||
};
|
||||
|
||||
return span;
|
||||
});
|
||||
}
|
||||
|
||||
async #walkSpanAncestors(
|
||||
event: PreparedEvent,
|
||||
callback: (event: PreparedEvent, level: number) => { stop: boolean }
|
||||
) {
|
||||
const parentId = event.parentId;
|
||||
if (!parentId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const events = transformEvents(
|
||||
span.data.events,
|
||||
fullEvent.metadata as Attributes,
|
||||
traceSummary?.rootSpan.data.environmentType === "DEVELOPMENT"
|
||||
);
|
||||
await startActiveSpan("walkSpanAncestors", async (s) => {
|
||||
let parentEvent = await this.#getSpanEvent(parentId);
|
||||
let level = 1;
|
||||
|
||||
return {
|
||||
...fullEvent,
|
||||
...span.data,
|
||||
payload,
|
||||
output,
|
||||
properties,
|
||||
events,
|
||||
show,
|
||||
links,
|
||||
};
|
||||
while (parentEvent) {
|
||||
const preparedParentEvent = prepareEvent(parentEvent);
|
||||
|
||||
const result = callback(preparedParentEvent, level);
|
||||
|
||||
if (result.stop) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!preparedParentEvent.parentId) {
|
||||
return;
|
||||
}
|
||||
|
||||
parentEvent = await this.#getSpanEvent(preparedParentEvent.parentId);
|
||||
|
||||
level++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async #getSpanAncestors(event: PreparedEvent, levels = 1): Promise<Array<PreparedEvent>> {
|
||||
if (levels >= 8) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!event.parentId) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const parentEvent = await this.#getSpanEvent(event.parentId);
|
||||
|
||||
if (!parentEvent) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const preparedParentEvent = prepareEvent(parentEvent);
|
||||
|
||||
if (!preparedParentEvent.parentId) {
|
||||
return [preparedParentEvent];
|
||||
}
|
||||
|
||||
const moreAncestors = await this.#getSpanAncestors(preparedParentEvent, levels + 1);
|
||||
|
||||
return [preparedParentEvent, ...moreAncestors];
|
||||
}
|
||||
|
||||
async #getSpanEvent(spanId: string) {
|
||||
return await startActiveSpan("getSpanEvent", async (s) => {
|
||||
const events = await this.readReplica.taskEvent.findMany({
|
||||
where: {
|
||||
spanId,
|
||||
},
|
||||
orderBy: {
|
||||
startTime: "asc",
|
||||
},
|
||||
});
|
||||
|
||||
let finalEvent: TaskEvent | undefined;
|
||||
|
||||
for (const event of events) {
|
||||
if (event.isPartial && finalEvent) {
|
||||
continue;
|
||||
}
|
||||
|
||||
finalEvent = event;
|
||||
}
|
||||
|
||||
return finalEvent;
|
||||
});
|
||||
}
|
||||
|
||||
public async recordEvent(message: string, options: TraceEventOptions) {
|
||||
@@ -1224,7 +1413,7 @@ function getNowInNanoseconds(): bigint {
|
||||
return BigInt(new Date().getTime() * 1_000_000);
|
||||
}
|
||||
|
||||
function getDateFromNanoseconds(nanoseconds: bigint) {
|
||||
export function getDateFromNanoseconds(nanoseconds: bigint) {
|
||||
return new Date(Number(nanoseconds) / 1_000_000);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { env } from "~/env.server";
|
||||
import { AuthenticatedEnvironment } from "~/services/apiAuth.server";
|
||||
import { logger } from "~/services/logger.server";
|
||||
import { singleton } from "~/utils/singleton";
|
||||
import { startActiveSpan } from "./tracer.server";
|
||||
|
||||
export const r2 = singleton("r2", initializeR2);
|
||||
|
||||
@@ -23,30 +24,87 @@ export async function uploadToObjectStore(
|
||||
contentType: string,
|
||||
environment: AuthenticatedEnvironment
|
||||
): Promise<string> {
|
||||
if (!r2) {
|
||||
throw new Error("Object store credentials are not set");
|
||||
return await startActiveSpan("uploadToObjectStore()", async (span) => {
|
||||
if (!r2) {
|
||||
throw new Error("Object store credentials are not set");
|
||||
}
|
||||
|
||||
if (!env.OBJECT_STORE_BASE_URL) {
|
||||
throw new Error("Object store base URL is not set");
|
||||
}
|
||||
|
||||
span.setAttributes({
|
||||
projectRef: environment.project.externalRef,
|
||||
environmentSlug: environment.slug,
|
||||
filename: filename,
|
||||
});
|
||||
|
||||
const url = new URL(env.OBJECT_STORE_BASE_URL);
|
||||
url.pathname = `/packets/${environment.project.externalRef}/${environment.slug}/${filename}`;
|
||||
|
||||
logger.debug("Uploading to object store", { url: url.href });
|
||||
|
||||
const response = await r2.fetch(url.toString(), {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": contentType,
|
||||
},
|
||||
body: data,
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to upload output to ${url}: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return url.href;
|
||||
});
|
||||
}
|
||||
|
||||
export async function generatePresignedRequest(
|
||||
projectRef: string,
|
||||
envSlug: string,
|
||||
filename: string,
|
||||
method: "PUT" | "GET" = "PUT"
|
||||
) {
|
||||
if (!env.OBJECT_STORE_BASE_URL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!env.OBJECT_STORE_BASE_URL) {
|
||||
throw new Error("Object store base URL is not set");
|
||||
if (!r2) {
|
||||
return;
|
||||
}
|
||||
|
||||
const url = new URL(env.OBJECT_STORE_BASE_URL);
|
||||
url.pathname = `/packets/${environment.project.externalRef}/${environment.slug}/${filename}`;
|
||||
url.pathname = `/packets/${projectRef}/${envSlug}/${filename}`;
|
||||
url.searchParams.set("X-Amz-Expires", "300"); // 5 minutes
|
||||
|
||||
logger.debug("Uploading to object store", { url: url.href });
|
||||
const signed = await r2.sign(
|
||||
new Request(url, {
|
||||
method,
|
||||
}),
|
||||
{
|
||||
aws: { signQuery: true },
|
||||
}
|
||||
);
|
||||
|
||||
const response = await r2.fetch(url.toString(), {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": contentType,
|
||||
},
|
||||
body: data,
|
||||
logger.debug("Generated presigned URL", {
|
||||
url: signed.url,
|
||||
headers: Object.fromEntries(signed.headers),
|
||||
projectRef,
|
||||
envSlug,
|
||||
filename,
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to upload output to ${url}: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return url.href;
|
||||
return signed;
|
||||
}
|
||||
|
||||
export async function generatePresignedUrl(
|
||||
projectRef: string,
|
||||
envSlug: string,
|
||||
filename: string,
|
||||
method: "PUT" | "GET" = "PUT"
|
||||
) {
|
||||
const signed = await generatePresignedRequest(projectRef, envSlug, filename, method);
|
||||
|
||||
return signed?.url;
|
||||
}
|
||||
|
||||
@@ -4,14 +4,15 @@ import {
|
||||
TriggerTaskRequestBody,
|
||||
packetRequiresOffloading,
|
||||
} from "@trigger.dev/core/v3";
|
||||
import { prisma } from "~/db.server";
|
||||
import { AuthenticatedEnvironment } from "~/services/apiAuth.server";
|
||||
import { autoIncrementCounter } from "~/services/autoIncrementCounter.server";
|
||||
import { marqs, sanitizeQueueName } from "~/v3/marqs/index.server";
|
||||
import { eventRepository } from "../eventRepository.server";
|
||||
import { generateFriendlyId } from "../friendlyIdentifiers";
|
||||
import { uploadToObjectStore } from "../r2.server";
|
||||
import { startActiveSpan } from "../tracer.server";
|
||||
import { BaseService } from "./baseService.server";
|
||||
import { env } from "~/env.server";
|
||||
|
||||
export type TriggerTaskServiceOptions = {
|
||||
idempotencyKey?: string;
|
||||
@@ -257,26 +258,31 @@ export class TriggerTaskService extends BaseService {
|
||||
pathPrefix: string,
|
||||
environment: AuthenticatedEnvironment
|
||||
) {
|
||||
const packet = this.#createPayloadPacket(payload, payloadType);
|
||||
return await startActiveSpan("handlePayloadPacket()", async (span) => {
|
||||
const packet = this.#createPayloadPacket(payload, payloadType);
|
||||
|
||||
if (!packet.data) {
|
||||
return packet;
|
||||
}
|
||||
if (!packet.data) {
|
||||
return packet;
|
||||
}
|
||||
|
||||
const { needsOffloading, size } = packetRequiresOffloading(packet);
|
||||
const { needsOffloading, size } = packetRequiresOffloading(
|
||||
packet,
|
||||
env.TASK_PAYLOAD_OFFLOAD_THRESHOLD
|
||||
);
|
||||
|
||||
if (!needsOffloading) {
|
||||
return packet;
|
||||
}
|
||||
if (!needsOffloading) {
|
||||
return packet;
|
||||
}
|
||||
|
||||
const filename = `${pathPrefix}/payload.json`;
|
||||
const filename = `${pathPrefix}/payload.json`;
|
||||
|
||||
await uploadToObjectStore(filename, packet.data, packet.dataType, environment);
|
||||
await uploadToObjectStore(filename, packet.data, packet.dataType, environment);
|
||||
|
||||
return {
|
||||
data: filename,
|
||||
dataType: "application/store",
|
||||
};
|
||||
return {
|
||||
data: filename,
|
||||
dataType: "application/store",
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
#createPayloadPacket(payload: any, payloadType: string): IOPacket {
|
||||
|
||||
@@ -117,7 +117,7 @@ function getTracer() {
|
||||
const samplingRate = 1.0 / Math.max(parseInt(env.INTERNAL_OTEL_TRACE_SAMPLING_RATE, 10), 1);
|
||||
|
||||
const provider = new NodeTracerProvider({
|
||||
forceFlushTimeoutMillis: 5000,
|
||||
forceFlushTimeoutMillis: 15_000,
|
||||
resource: new Resource({
|
||||
[SEMRESATTRS_SERVICE_NAME]: env.SERVICE_NAME,
|
||||
}),
|
||||
@@ -129,7 +129,7 @@ function getTracer() {
|
||||
if (env.INTERNAL_OTEL_TRACE_EXPORTER_URL) {
|
||||
const exporter = new OTLPTraceExporter({
|
||||
url: env.INTERNAL_OTEL_TRACE_EXPORTER_URL,
|
||||
timeoutMillis: 10_000,
|
||||
timeoutMillis: 15_000,
|
||||
headers:
|
||||
env.INTERNAL_OTEL_TRACE_EXPORTER_AUTH_HEADER_NAME &&
|
||||
env.INTERNAL_OTEL_TRACE_EXPORTER_AUTH_HEADER_VALUE
|
||||
|
||||
@@ -1722,10 +1722,18 @@ components:
|
||||
type: object
|
||||
description: The payload that was sent to the task. Will be omitted if the request was made with a Public API key
|
||||
example: { "foo": "bar" }
|
||||
payloadPresignedUrl:
|
||||
type: string
|
||||
description: The presigned URL to download the payload. Will only be included if the payload is too large to be included in the response. Expires in 5 minutes.
|
||||
example: "https://r2.cloudflarestorage.com/packets/yubjwjsfkxnylobaqvqz/dev/run_p4omhh45hgxxnq1re6ovy/payload.json?X-Amz-Expires=300&X-Amz-Date=20240625T154526Z&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=10b064e58a0680db5b5e077be2be3b2a%2F20240625%2Fauto%2Fs3%2Faws4_request&X-Amz-SignedHeaders=host&X-Amz-Signature=88604cb993ffc151b4d73f2439da431d9928488e4b3dcfa4a7c8f1819"
|
||||
output:
|
||||
type: object
|
||||
description: The output of the run. Will be omitted if the request was made with a Public API key
|
||||
example: { "foo": "bar" }
|
||||
outputPresignedUrl:
|
||||
type: string
|
||||
description: The presigned URL to download the output. Will only be included if the output is too large to be included in the response. Expires in 5 minutes.
|
||||
example: "https://r2.cloudflarestorage.com/packets/yubjwjsfkxnylobaqvqz/dev/run_p4omhh45hgxxnq1re6ovy/payload.json?X-Amz-Expires=300&X-Amz-Date=20240625T154526Z&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=10b064e58a0680db5b5e077be2be3b2a%2F20240625%2Fauto%2Fs3%2Faws4_request&X-Amz-SignedHeaders=host&X-Amz-Signature=88604cb993ffc151b4d73f2439da431d9928488e4b3dcfa4a7c8f1819"
|
||||
idempotencyKey:
|
||||
type: string
|
||||
description: The idempotency key used to prevent creating duplicate runs, if provided
|
||||
|
||||
@@ -37,3 +37,13 @@ If you add them dynamically using code make sure you add a `deduplicationKey` so
|
||||
If you're creating schedules for your user you will definitely need to request more schedules from us.
|
||||
|
||||
<Snippet file="v3/soft-limit.mdx" />
|
||||
|
||||
## Task payloads and outputs
|
||||
|
||||
| Limit | Details |
|
||||
| ---------------------- | ---------------------------------------------- |
|
||||
| Single trigger payload | Must not exceed 10MB |
|
||||
| Batch trigger payload | The total of all payloads must not exceed 10MB |
|
||||
| Task outputs | Must not exceed 10MB |
|
||||
|
||||
Payloads and outputs that exceed 512KB will be offloaded to object storage and a presigned URL will be provided to download the data when calling `runs.retrieve`. You don't need to do anything to handle this in your tasks however, as we will transparently upload/download these during operation.
|
||||
|
||||
@@ -536,3 +536,86 @@ export async function create() {
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Large Payloads
|
||||
|
||||
We recommend keeping your task payloads as small as possible. We currently have a hard limit on task payloads above 10MB.
|
||||
|
||||
If your payload size is larger than 512KB, instead of saving the payload to the database, we will upload it to an S3-compatible object store and store the URL in the database.
|
||||
|
||||
When your task runs, we automatically download the payload from the object store and pass it to your task function. We also will return to you a `payloadPresignedUrl` from the `runs.retrieve` SDK function so you can download the payload if needed:
|
||||
|
||||
```ts
|
||||
import { runs } from "@trigger.dev/sdk/v3";
|
||||
|
||||
const run = await runs.retrieve(handle);
|
||||
|
||||
if (run.payloadPresignedUrl) {
|
||||
const response = await fetch(run.payloadPresignedUrl);
|
||||
const payload = await response.json();
|
||||
|
||||
console.log("Payload", payload);
|
||||
}
|
||||
```
|
||||
|
||||
<Note>
|
||||
We also use this same system for dealing with large task outputs, and subsequently will return a
|
||||
corresponding `outputPresignedUrl`. Task outputs are limited to 100MB.
|
||||
</Note>
|
||||
|
||||
If you need to pass larger payloads, you'll need to upload the payload to your own storage and pass a URL to the file in the payload instead. For example, uploading to S3 and then sending a presigned URL that expires in URL:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```ts /yourServer.ts
|
||||
import { myTask } from "./trigger/myTasks";
|
||||
import { s3Client, getSignedUrl, PutObjectCommand, GetObjectCommand } from "./s3";
|
||||
import { createReadStream } from "node:fs";
|
||||
|
||||
// Upload file to S3
|
||||
await s3Client.send(
|
||||
new PutObjectCommand({
|
||||
Bucket: "my-bucket",
|
||||
Key: "myfile.json",
|
||||
Body: createReadStream("large-payload.json"),
|
||||
})
|
||||
);
|
||||
|
||||
// Create presigned URL
|
||||
const presignedUrl = await getSignedUrl(
|
||||
s3Client,
|
||||
new GetObjectCommand({
|
||||
Bucket: "my-bucket",
|
||||
Key: "my-file.json",
|
||||
}),
|
||||
{
|
||||
expiresIn: 3600, // expires in 1 hour
|
||||
}
|
||||
);
|
||||
|
||||
// Now send the URL to the task
|
||||
const handle = await myTask.trigger({
|
||||
url: presignedUrl,
|
||||
});
|
||||
```
|
||||
|
||||
```ts /trigger/myTasks.ts
|
||||
import { task } from "@trigger.dev/sdk/v3";
|
||||
|
||||
export const myTask = task({
|
||||
id: "my-task",
|
||||
run: async (payload: { url: string }) => {
|
||||
// Download the file from the URL
|
||||
const response = await fetch(payload.url);
|
||||
const data = await response.json();
|
||||
|
||||
// Do something with the data
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### Batch Triggering
|
||||
|
||||
When using `batchTrigger` or `batchTriggerAndWait`, the total size of all payloads cannot exceed 10MB. This means if you are doing a batch of 100 runs, each payload should be less than 100KB.
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
# @trigger.dev/airtable
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.44
|
||||
- @trigger.dev/sdk@3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [34ca7667d]
|
||||
- @trigger.dev/sdk@3.0.0-beta.43
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ecef19966]
|
||||
- @trigger.dev/sdk@3.0.0-beta.42
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/airtable",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "Trigger.dev integration for airtable",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -25,8 +25,8 @@
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.44",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.44",
|
||||
"airtable": "^0.12.1",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
# @trigger.dev/github
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.44
|
||||
- @trigger.dev/sdk@3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [34ca7667d]
|
||||
- @trigger.dev/sdk@3.0.0-beta.43
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ecef19966]
|
||||
- @trigger.dev/sdk@3.0.0-beta.42
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/github",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "The official GitHub integration for Trigger.dev",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -30,8 +30,8 @@
|
||||
"@octokit/request-error": "^5.0.1",
|
||||
"@octokit/webhooks": "^12.0.10",
|
||||
"octokit": "^3.1.2",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.44",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.44",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
# @trigger.dev/linear
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.44
|
||||
- @trigger.dev/sdk@3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [34ca7667d]
|
||||
- @trigger.dev/sdk@3.0.0-beta.43
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ecef19966]
|
||||
- @trigger.dev/sdk@3.0.0-beta.42
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/linear",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "Trigger.dev integration for @linear/sdk",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -26,8 +26,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@linear/sdk": "^8.0.0",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.44",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.44",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
# @trigger.dev/slack
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.44
|
||||
- @trigger.dev/sdk@3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [34ca7667d]
|
||||
- @trigger.dev/sdk@3.0.0-beta.43
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ecef19966]
|
||||
- @trigger.dev/sdk@3.0.0-beta.42
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/openai",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "The official OpenAI integration for Trigger.dev",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -42,8 +42,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"openai": "^4.16.1",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.41"
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.44",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.44"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
# @trigger.dev/plain
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.44
|
||||
- @trigger.dev/sdk@3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [34ca7667d]
|
||||
- @trigger.dev/sdk@3.0.0-beta.43
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ecef19966]
|
||||
- @trigger.dev/sdk@3.0.0-beta.42
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/plain",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "The official Plain.com integration for Trigger.dev",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -24,8 +24,8 @@
|
||||
"build:tsup": "tsup"
|
||||
},
|
||||
"dependencies": {
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.44",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.44",
|
||||
"@team-plain/typescript-sdk": "^2.7.0"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
# @trigger.dev/replicate
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.44
|
||||
- @trigger.dev/sdk@3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [34ca7667d]
|
||||
- @trigger.dev/sdk@3.0.0-beta.43
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ecef19966]
|
||||
- @trigger.dev/sdk@3.0.0-beta.42
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/replicate",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "Trigger.dev integration for replicate",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -25,8 +25,8 @@
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.44",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.44",
|
||||
"replicate": "^0.18.1",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
# @trigger.dev/resend
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.44
|
||||
- @trigger.dev/sdk@3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [34ca7667d]
|
||||
- @trigger.dev/sdk@3.0.0-beta.43
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ecef19966]
|
||||
- @trigger.dev/sdk@3.0.0-beta.42
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/resend",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "The official Resend.com integration for Trigger.dev",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -24,8 +24,8 @@
|
||||
"build:tsup": "tsup"
|
||||
},
|
||||
"dependencies": {
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.44",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.44",
|
||||
"resend": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
# @trigger.dev/sendgrid
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.44
|
||||
- @trigger.dev/sdk@3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [34ca7667d]
|
||||
- @trigger.dev/sdk@3.0.0-beta.43
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ecef19966]
|
||||
- @trigger.dev/sdk@3.0.0-beta.42
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/sendgrid",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "Trigger.dev integration for @sendgrid/mail",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -26,8 +26,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@sendgrid/mail": "^7.7.0",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.41"
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.44",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.44"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.8.0"
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
# @trigger.dev/shopify
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.44
|
||||
- @trigger.dev/sdk@3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [34ca7667d]
|
||||
- @trigger.dev/sdk@3.0.0-beta.43
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ecef19966]
|
||||
- @trigger.dev/sdk@3.0.0-beta.42
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/shopify",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "Trigger.dev integration for @shopify/shopify-api",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -26,8 +26,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@shopify/shopify-api": "^8.0.2",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.44",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.44",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -1,5 +1,25 @@
|
||||
# @trigger.dev/slack
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/sdk@3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [34ca7667d]
|
||||
- @trigger.dev/sdk@3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ecef19966]
|
||||
- @trigger.dev/sdk@3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/slack",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "The official Slack integration for Trigger.dev",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -25,7 +25,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@slack/web-api": "^6.8.1",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.44",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
# @trigger.dev/stripe
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.44
|
||||
- @trigger.dev/sdk@3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [34ca7667d]
|
||||
- @trigger.dev/sdk@3.0.0-beta.43
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ecef19966]
|
||||
- @trigger.dev/sdk@3.0.0-beta.42
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/stripe",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "Trigger.dev integration for stripe",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -25,8 +25,8 @@
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.44",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.44",
|
||||
"stripe": "^12.14.0",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
# @trigger.dev/supabase
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.44
|
||||
- @trigger.dev/sdk@3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [34ca7667d]
|
||||
- @trigger.dev/sdk@3.0.0-beta.43
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ecef19966]
|
||||
- @trigger.dev/sdk@3.0.0-beta.42
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/supabase",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "Trigger.dev integration for @supabase/supabase-js",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -26,8 +26,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@supabase/supabase-js": "^2.26.0",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.44",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.44",
|
||||
"supabase-management-js": "^1.0.0",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
# @trigger.dev/typeform
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.44
|
||||
- @trigger.dev/sdk@3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [34ca7667d]
|
||||
- @trigger.dev/sdk@3.0.0-beta.43
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ecef19966]
|
||||
- @trigger.dev/sdk@3.0.0-beta.42
|
||||
- @trigger.dev/integration-kit@3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/typeform",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "The official Typeform integration for Trigger.dev",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -24,8 +24,8 @@
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/integration-kit": "workspace:^3.0.0-beta.44",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.44",
|
||||
"@typeform/api-client": "^1.8.0",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,25 @@
|
||||
# @trigger.dev/astro
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/sdk@3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [34ca7667d]
|
||||
- @trigger.dev/sdk@3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ecef19966]
|
||||
- @trigger.dev/sdk@3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@trigger.dev/astro",
|
||||
"description": "An Astro-native integration for Trigger.dev background jobs platform",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
@@ -20,7 +20,7 @@
|
||||
"build:tsup": "tsup"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.41"
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.44"
|
||||
},
|
||||
"devDependencies": {
|
||||
"astro": "^3.0.12",
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
# trigger.dev
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [39885a427]
|
||||
- @trigger.dev/core@3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 77ad4127c: Improved ESM module require error detection logic
|
||||
- Updated dependencies [34ca7667d]
|
||||
- @trigger.dev/core@3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/core@3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "trigger.dev",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "A Command-Line Interface for Trigger.dev (v3) projects",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -87,7 +87,7 @@
|
||||
"@opentelemetry/sdk-trace-base": "^1.22.0",
|
||||
"@opentelemetry/sdk-trace-node": "^1.22.0",
|
||||
"@opentelemetry/semantic-conventions": "^1.22.0",
|
||||
"@trigger.dev/core": "workspace:3.0.0-beta.41",
|
||||
"@trigger.dev/core": "workspace:3.0.0-beta.44",
|
||||
"@types/degit": "^2.8.3",
|
||||
"chalk": "^5.2.0",
|
||||
"chokidar": "^3.5.3",
|
||||
|
||||
@@ -640,6 +640,10 @@ function useDev({
|
||||
backgroundWorker
|
||||
);
|
||||
} catch (e) {
|
||||
logger.debug("Error starting background worker", {
|
||||
error: e,
|
||||
});
|
||||
|
||||
if (e instanceof TaskMetadataParseError) {
|
||||
logTaskMetadataParseError(e.zodIssues, e.tasks);
|
||||
return;
|
||||
|
||||
@@ -28,17 +28,10 @@ export function parseBuildErrorStack(error: unknown): BuildError | undefined {
|
||||
|
||||
if (errorIsErrorLike(error)) {
|
||||
if (typeof error.stack === "string") {
|
||||
const isErrRequireEsm = error.stack.includes("ERR_REQUIRE_ESM");
|
||||
|
||||
let moduleName = null;
|
||||
|
||||
if (isErrRequireEsm) {
|
||||
// Regular expression to match the module path
|
||||
const moduleRegex = /node_modules\/(@[^\/]+\/[^\/]+|[^\/]+)\/[^\/]+\s/;
|
||||
const match = moduleRegex.exec(error.stack);
|
||||
if (match) {
|
||||
moduleName = match[1] as string; // Capture the module name
|
||||
if (error.stack.includes("ERR_REQUIRE_ESM")) {
|
||||
const moduleName = getPackageNameFromEsmRequireError(error.stack);
|
||||
|
||||
if (moduleName) {
|
||||
return {
|
||||
type: "esm-require-error",
|
||||
moduleName,
|
||||
@@ -51,6 +44,38 @@ export function parseBuildErrorStack(error: unknown): BuildError | undefined {
|
||||
}
|
||||
}
|
||||
|
||||
function getPackageNameFromEsmRequireError(stack: string): string | undefined {
|
||||
const pathRegex = /require\(\) of ES Module (.*) from/;
|
||||
const pathMatch = pathRegex.exec(stack);
|
||||
|
||||
if (!pathMatch) {
|
||||
return;
|
||||
}
|
||||
|
||||
const filePath = pathMatch[1];
|
||||
|
||||
if (!filePath) {
|
||||
return;
|
||||
}
|
||||
|
||||
const lastPart = filePath.split("node_modules/").pop();
|
||||
|
||||
if (!lastPart) {
|
||||
return;
|
||||
}
|
||||
|
||||
// regular expression to match the package name
|
||||
const moduleRegex = /(@[^\/]+\/[^\/]+|[^\/]+)/;
|
||||
|
||||
const match = moduleRegex.exec(lastPart);
|
||||
|
||||
if (!match) {
|
||||
return;
|
||||
}
|
||||
|
||||
return match[1];
|
||||
}
|
||||
|
||||
export function logESMRequireError(parsedError: ESMRequireError, resolvedConfig: ReadConfigResult) {
|
||||
logger.log(
|
||||
`\n${chalkError("X Error:")} The ${chalkPurple(
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
# create-trigger
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [39885a427]
|
||||
- @trigger.dev/core@3.0.0-beta.44
|
||||
- @trigger.dev/yalt@3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [34ca7667d]
|
||||
- @trigger.dev/core@3.0.0-beta.43
|
||||
- @trigger.dev/yalt@3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/core@3.0.0-beta.42
|
||||
- @trigger.dev/yalt@3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/cli",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "The Trigger.dev CLI",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @trigger.dev/core-apps
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@trigger.dev/core-apps",
|
||||
"description": "Backend core code used across apps",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @trigger.dev/core-backend
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/core-backend",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "Core code used across `@trigger.dev/sdk` and Trigger.dev server",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# internal-platform
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 39885a427: v3: fix missing init output in task run function when no middleware is defined
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 34ca7667d: v3: Include presigned urls for downloading large payloads and outputs when using runs.retrieve
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/core",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "Core code used across the Trigger.dev SDK and platform",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
@@ -85,6 +85,14 @@
|
||||
"require": "./dist/v3/utils/structuredLogger.js",
|
||||
"types": "./dist/v3/utils/structuredLogger.d.ts"
|
||||
},
|
||||
"./v3/utils/durations": {
|
||||
"import": {
|
||||
"types": "./dist/v3/utils/durations.d.mts",
|
||||
"default": "./dist/v3/utils/durations.mjs"
|
||||
},
|
||||
"require": "./dist/v3/utils/durations.js",
|
||||
"types": "./dist/v3/utils/durations.d.ts"
|
||||
},
|
||||
"./v3/dev": {
|
||||
"import": {
|
||||
"types": "./dist/v3/dev/index.d.mts",
|
||||
|
||||
@@ -431,7 +431,9 @@ const CommonRunFields = {
|
||||
export const RetrieveRunResponse = z.object({
|
||||
...CommonRunFields,
|
||||
payload: z.any().optional(),
|
||||
payloadPresignedUrl: z.string().optional(),
|
||||
output: z.any().optional(),
|
||||
outputPresignedUrl: z.string().optional(),
|
||||
schedule: RunScheduleDetails.optional(),
|
||||
attempts: z.array(
|
||||
z
|
||||
|
||||
@@ -85,7 +85,10 @@ export async function conditionallyExportPacket(
|
||||
return packet;
|
||||
}
|
||||
|
||||
export function packetRequiresOffloading(packet: IOPacket): {
|
||||
export function packetRequiresOffloading(
|
||||
packet: IOPacket,
|
||||
lengthLimit?: number
|
||||
): {
|
||||
needsOffloading: boolean;
|
||||
size: number;
|
||||
} {
|
||||
@@ -99,7 +102,7 @@ export function packetRequiresOffloading(packet: IOPacket): {
|
||||
const byteSize = Buffer.byteLength(packet.data, "utf8");
|
||||
|
||||
return {
|
||||
needsOffloading: byteSize >= OFFLOAD_IO_PACKET_LENGTH_LIMIT,
|
||||
needsOffloading: byteSize >= (lengthLimit ?? OFFLOAD_IO_PACKET_LENGTH_LIMIT),
|
||||
size: byteSize,
|
||||
};
|
||||
}
|
||||
@@ -128,8 +131,6 @@ async function exportPacket(packet: IOPacket, pathPrefix: string): Promise<IOPac
|
||||
data: filename,
|
||||
dataType: "application/store",
|
||||
};
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
export async function conditionallyImportPacket(
|
||||
@@ -186,8 +187,6 @@ async function importPacket(packet: IOPacket, span?: Span): Promise<IOPacket> {
|
||||
data,
|
||||
dataType: response.headers.get("content-type") ?? "application/json",
|
||||
};
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
export async function createPacketAttributes(
|
||||
|
||||
@@ -229,7 +229,7 @@ export class TaskExecutor {
|
||||
}
|
||||
|
||||
if (!middlewareFn) {
|
||||
return runFn(payload, { ctx });
|
||||
return runFn(payload, { ctx, init });
|
||||
}
|
||||
|
||||
return middlewareFn(payload, { ctx, next: async () => runFn(payload, { ctx, init }) });
|
||||
|
||||
@@ -172,7 +172,11 @@ export class ZodMessageSender<TMessageCatalog extends ZodMessageCatalogSchema> {
|
||||
throw new ZodSchemaParsedError(parsedPayload.error, payload);
|
||||
}
|
||||
|
||||
await this.#sender({ type, payload, version: "v1" });
|
||||
try {
|
||||
await this.#sender({ type, payload, version: "v1" });
|
||||
} catch (error) {
|
||||
console.error("[ZodMessageSender] Failed to send message", error);
|
||||
}
|
||||
}
|
||||
|
||||
public async forwardMessage(message: unknown) {
|
||||
@@ -194,11 +198,15 @@ export class ZodMessageSender<TMessageCatalog extends ZodMessageCatalogSchema> {
|
||||
throw new Error(`Failed to parse message payload: ${JSON.stringify(parsedPayload.error)}`);
|
||||
}
|
||||
|
||||
await this.#sender({
|
||||
type: parsedMessage.data.type,
|
||||
payload: parsedPayload.data,
|
||||
version: "v1",
|
||||
});
|
||||
try {
|
||||
await this.#sender({
|
||||
type: parsedMessage.data.type,
|
||||
payload: parsedPayload.data,
|
||||
version: "v1",
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("[ZodMessageSender] Failed to forward message", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ export default defineConfig({
|
||||
"./src/v3/zodSocket.ts",
|
||||
"./src/v3/zodIpc.ts",
|
||||
"./src/v3/utils/structuredLogger.ts",
|
||||
"./src/v3/utils/durations.ts",
|
||||
"./src/v3/dev/index.ts",
|
||||
"./src/v3/prod/index.ts",
|
||||
"./src/v3/workers/index.ts",
|
||||
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
-- CreateIndex
|
||||
CREATE INDEX "TaskEvent_runId_idx" ON "TaskEvent"("runId");
|
||||
@@ -1925,6 +1925,8 @@ model TaskEvent {
|
||||
@@index([traceId])
|
||||
/// Used when looking up span events to complete when a run completes
|
||||
@@index([spanId])
|
||||
// Used for getting all logs for a run
|
||||
@@index([runId])
|
||||
}
|
||||
|
||||
enum TaskEventLevel {
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @trigger.dev/eslint-plugin
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/eslint-plugin",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "ESLint plugin with trigger.dev best practices",
|
||||
"keywords": [
|
||||
"eslint",
|
||||
|
||||
@@ -1,5 +1,25 @@
|
||||
# @trigger.dev/express
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/sdk@3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [34ca7667d]
|
||||
- @trigger.dev/sdk@3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ecef19966]
|
||||
- @trigger.dev/sdk@3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/express",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "Official Express adapter for Trigger.dev",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
@@ -23,7 +23,7 @@
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.44",
|
||||
"@trigger.dev/tsconfig": "workspace:*",
|
||||
"@types/debug": "^4.1.7",
|
||||
"@types/express": "^4.17.13",
|
||||
@@ -39,7 +39,7 @@
|
||||
"build:tsup": "tsup"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.41"
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.44"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": "^4.3.4",
|
||||
|
||||
@@ -1,5 +1,25 @@
|
||||
# @trigger.dev/hono
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/sdk@3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [34ca7667d]
|
||||
- @trigger.dev/sdk@3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ecef19966]
|
||||
- @trigger.dev/sdk@3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/hono",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "A Trigger.dev adapter for Hono.dev",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
@@ -32,7 +32,7 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"hono": "3.x",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.41"
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.44"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@trigger.dev/tsconfig": "workspace:*",
|
||||
|
||||
@@ -1,5 +1,25 @@
|
||||
# @trigger.dev/integration-kit
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [39885a427]
|
||||
- @trigger.dev/core@3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [34ca7667d]
|
||||
- @trigger.dev/core@3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/core@3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/integration-kit",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "Trigger.dev Integration Kit has helpers to make creating integrations easier",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
|
||||
@@ -1,5 +1,25 @@
|
||||
# @trigger.dev/nestjs
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/sdk@3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [34ca7667d]
|
||||
- @trigger.dev/sdk@3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ecef19966]
|
||||
- @trigger.dev/sdk@3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/nestjs",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "Official NestJS adapter for Trigger.dev",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
@@ -23,7 +23,7 @@
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.44",
|
||||
"@trigger.dev/tsconfig": "workspace:*",
|
||||
"@types/debug": "^4.1.7",
|
||||
"@types/express": "^4.17.13",
|
||||
@@ -41,7 +41,7 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@nestjs/common": ">=10.0.0",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.41"
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.44"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nestjs/common": "^10.2.4",
|
||||
|
||||
@@ -1,5 +1,25 @@
|
||||
# @trigger.dev/nextjs
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/sdk@3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [34ca7667d]
|
||||
- @trigger.dev/sdk@3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ecef19966]
|
||||
- @trigger.dev/sdk@3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/nextjs",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "Trigger.dev Next.js integration",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
@@ -41,7 +41,7 @@
|
||||
"build:tsup": "tsup"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.44",
|
||||
"next": ">=12.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @trigger.dev/otlp-importer
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
## 3.0.0-beta.40
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/otlp-importer",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "OpenTelemetry OTLP Importer for Node.js written in TypeScript",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
|
||||
@@ -1,5 +1,25 @@
|
||||
# @trigger.dev/react
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [39885a427]
|
||||
- @trigger.dev/core@3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [34ca7667d]
|
||||
- @trigger.dev/core@3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/core@3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/react",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "Trigger.dev React SDK",
|
||||
"license": "MIT",
|
||||
"types": "dist/index.d.ts",
|
||||
@@ -27,7 +27,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@tanstack/react-query": "5.0.0-beta.2",
|
||||
"@trigger.dev/core": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/core": "workspace:^3.0.0-beta.44",
|
||||
"debug": "^4.3.4",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,25 @@
|
||||
# @trigger.dev/remix
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/sdk@3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [34ca7667d]
|
||||
- @trigger.dev/sdk@3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ecef19966]
|
||||
- @trigger.dev/sdk@3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/remix",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "Trigger.dev Remix integration",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
@@ -39,7 +39,7 @@
|
||||
"build:tsup": "tsup"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.41",
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.44",
|
||||
"@remix-run/server-runtime": ">1.19.0"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,5 +1,25 @@
|
||||
# @trigger.dev/sveltekit
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @trigger.dev/sdk@3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [34ca7667d]
|
||||
- @trigger.dev/sdk@3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ecef19966]
|
||||
- @trigger.dev/sdk@3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@trigger.dev/sveltekit",
|
||||
"version": "3.0.0-beta.41",
|
||||
"version": "3.0.0-beta.44",
|
||||
"description": "Trigger.dev svelteKit integration",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
@@ -39,7 +39,7 @@
|
||||
"build:tsup": "tsup"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.41"
|
||||
"@trigger.dev/sdk": "workspace:^3.0.0-beta.44"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": "^4.3.4"
|
||||
|
||||
@@ -1,5 +1,29 @@
|
||||
# @trigger.dev/testing
|
||||
|
||||
## 3.0.0-beta.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [39885a427]
|
||||
- @trigger.dev/core@3.0.0-beta.44
|
||||
- @trigger.dev/sdk@3.0.0-beta.44
|
||||
|
||||
## 3.0.0-beta.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [34ca7667d]
|
||||
- @trigger.dev/core@3.0.0-beta.43
|
||||
- @trigger.dev/sdk@3.0.0-beta.43
|
||||
|
||||
## 3.0.0-beta.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ecef19966]
|
||||
- @trigger.dev/sdk@3.0.0-beta.42
|
||||
- @trigger.dev/core@3.0.0-beta.42
|
||||
|
||||
## 3.0.0-beta.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user