Skip to content

Commit 9c28bde

Browse files
committed
Completing and skipping waitpoints is working
1 parent 14468c9 commit 9c28bde

File tree

5 files changed

+191
-135
lines changed

5 files changed

+191
-135
lines changed

apps/webapp/app/presenters/v3/SpanPresenter.server.ts

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { machinePresetFromName } from "~/v3/machinePresets.server";
1111
import { FINAL_ATTEMPT_STATUSES, isFailedRunStatus, isFinalRunStatus } from "~/v3/taskStatus";
1212
import { BasePresenter } from "./basePresenter.server";
1313
import { getMaxDuration } from "@trigger.dev/core/v3/apps";
14+
import { logger } from "~/services/logger.server";
1415

1516
type Result = Awaited<ReturnType<SpanPresenter["call"]>>;
1617
export type Span = NonNullable<NonNullable<Result>["span"]>;
@@ -43,6 +44,7 @@ export class SpanPresenter extends BasePresenter {
4344
const parentRun = await this._prisma.taskRun.findFirst({
4445
select: {
4546
traceId: true,
47+
runtimeEnvironmentId: true,
4648
},
4749
where: {
4850
friendlyId: runFriendlyId,
@@ -64,7 +66,7 @@ export class SpanPresenter extends BasePresenter {
6466
}
6567

6668
//get the run
67-
const span = await this.getSpan(traceId, spanId);
69+
const span = await this.getSpan(traceId, spanId, parentRun.runtimeEnvironmentId);
6870

6971
if (!span) {
7072
throw new Error("Span not found");
@@ -399,7 +401,7 @@ export class SpanPresenter extends BasePresenter {
399401
};
400402
}
401403

402-
async getSpan(traceId: string, spanId: string) {
404+
async getSpan(traceId: string, spanId: string, environmentId: string) {
403405
const span = await eventRepository.getSpan(spanId, traceId);
404406
if (!span) {
405407
return;
@@ -451,14 +453,42 @@ export class SpanPresenter extends BasePresenter {
451453
},
452454
});
453455

456+
if (!waitpoint) {
457+
logger.error(`SpanPresenter: Waitpoint not found`, {
458+
spanId,
459+
waitpointFriendlyId: span.entity.id,
460+
});
461+
return { ...data, entity: null };
462+
}
463+
464+
const output =
465+
waitpoint.outputType === "application/store"
466+
? `/resources/packets/${environmentId}/${waitpoint.output}`
467+
: typeof waitpoint.output !== "undefined" && waitpoint.output !== null
468+
? await prettyPrintPacket(waitpoint.output, waitpoint.outputType ?? undefined)
469+
: undefined;
470+
454471
return {
455472
...data,
456-
entityType: "waitpoint" as const,
457-
waitpoint,
473+
entity: {
474+
type: "waitpoint" as const,
475+
object: {
476+
friendlyId: waitpoint.friendlyId,
477+
type: waitpoint.type,
478+
status: waitpoint.status,
479+
idempotencyKey: waitpoint.idempotencyKey,
480+
userProvidedIdempotencyKey: waitpoint.userProvidedIdempotencyKey,
481+
idempotencyKeyExpiresAt: waitpoint.idempotencyKeyExpiresAt,
482+
output: output,
483+
outputType: waitpoint.outputType,
484+
outputIsError: waitpoint.outputIsError,
485+
completedAfter: waitpoint.completedAfter,
486+
},
487+
},
458488
};
459489

460490
default:
461-
return { ...data, entityType: "span" as const };
491+
return { ...data, entity: null };
462492
}
463493
}
464494
}

apps/webapp/app/routes/api.v1.waitpoints.tokens.$waitpointFriendlyId.complete.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
import { WaitpointId } from "@trigger.dev/core/v3/apps";
99
import { z } from "zod";
1010
import { $replica } from "~/db.server";
11+
import { env } from "~/env.server";
1112
import { logger } from "~/services/logger.server";
1213
import { createActionApiRoute } from "~/services/routeBuilders/apiBuilder.server";
1314
import { engine } from "~/v3/runEngine.server";
@@ -18,20 +19,14 @@ const { action } = createActionApiRoute(
1819
waitpointFriendlyId: z.string(),
1920
}),
2021
body: CompleteWaitpointTokenRequestBody,
21-
maxContentLength: 1024 * 10, // 10KB
22+
maxContentLength: env.TASK_PAYLOAD_MAXIMUM_SIZE,
2223
method: "POST",
2324
},
2425
async ({ authentication, body, params }) => {
2526
// Resume tokens are actually just waitpoints
2627
const waitpointId = WaitpointId.toId(params.waitpointFriendlyId);
2728

2829
try {
29-
const stringifiedData = await stringifyIO(body.data);
30-
const finalData = await conditionallyExportPacket(
31-
stringifiedData,
32-
`${waitpointId}/waitpoint/token`
33-
);
34-
3530
//check permissions
3631
const waitpoint = await $replica.waitpoint.findFirst({
3732
where: {
@@ -44,6 +39,12 @@ const { action } = createActionApiRoute(
4439
throw json({ error: "Waitpoint not found" }, { status: 404 });
4540
}
4641

42+
const stringifiedData = await stringifyIO(body.data);
43+
const finalData = await conditionallyExportPacket(
44+
stringifiedData,
45+
`${waitpointId}/waitpoint/token`
46+
);
47+
4748
const result = await engine.completeWaitpoint({
4849
id: waitpointId,
4950
output: finalData.data

apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.waitpoints.$waitpointFriendlyId.complete/route.tsx

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import { parse } from "@conform-to/zod";
22
import { InformationCircleIcon } from "@heroicons/react/20/solid";
33
import { Form, useLocation, useNavigation, useSubmit } from "@remix-run/react";
44
import { ActionFunctionArgs, json } from "@remix-run/server-runtime";
5+
import { conditionallyExportPacket, stringifyIO } from "@trigger.dev/core/v3";
56
import { WaitpointId } from "@trigger.dev/core/v3/apps";
67
import { Waitpoint } from "@trigger.dev/database";
7-
import { motion } from "framer-motion";
88
import { useCallback, useRef } from "react";
99
import { z } from "zod";
1010
import { AnimatedHourglassIcon } from "~/assets/icons/AnimatedHourglassIcon";
@@ -14,16 +14,14 @@ import { Button } from "~/components/primitives/Buttons";
1414
import { DateTime } from "~/components/primitives/DateTime";
1515
import { Paragraph } from "~/components/primitives/Paragraph";
1616
import { LiveCountdown } from "~/components/runs/v3/LiveTimer";
17-
import { $replica, prisma } from "~/db.server";
17+
import { $replica } from "~/db.server";
1818
import { useOrganization } from "~/hooks/useOrganizations";
1919
import { useProject } from "~/hooks/useProject";
2020
import { redirectWithErrorMessage, redirectWithSuccessMessage } from "~/models/message.server";
2121
import { logger } from "~/services/logger.server";
2222
import { requireUserId } from "~/services/session.server";
23-
import { ProjectParamSchema, v3RunsPath, v3SchedulesPath } from "~/utils/pathBuilder";
23+
import { ProjectParamSchema, v3RunsPath } from "~/utils/pathBuilder";
2424
import { engine } from "~/v3/runEngine.server";
25-
import { UpsertSchedule } from "~/v3/schedules";
26-
import { UpsertTaskScheduleService } from "~/v3/services/upsertTaskSchedule.server";
2725

2826
const CompleteWaitpointFormData = z.discriminatedUnion("type", [
2927
z.object({
@@ -106,8 +104,34 @@ export const action = async ({ request, params }: ActionFunctionArgs) => {
106104
);
107105
}
108106
case "MANUAL": {
109-
//todo packet
110-
//todo completeWaitpoint
107+
let data: any;
108+
try {
109+
data = JSON.parse(submission.value.payload);
110+
} catch (e) {
111+
return redirectWithErrorMessage(
112+
submission.value.failureRedirect,
113+
request,
114+
"Invalid payload, must be valid JSON"
115+
);
116+
}
117+
const stringifiedData = await stringifyIO(data);
118+
const finalData = await conditionallyExportPacket(
119+
stringifiedData,
120+
`${waitpointId}/waitpoint/token`
121+
);
122+
123+
const result = await engine.completeWaitpoint({
124+
id: waitpointId,
125+
output: finalData.data
126+
? { type: finalData.dataType, value: finalData.data, isError: false }
127+
: undefined,
128+
});
129+
130+
return redirectWithSuccessMessage(
131+
submission.value.successRedirect,
132+
request,
133+
"Waitpoint completed"
134+
);
111135
}
112136
}
113137
} catch (error: any) {
@@ -259,7 +283,7 @@ function CompleteManualWaitpointForm({ waitpoint }: { waitpoint: { friendlyId: s
259283
onSubmit={(e) => submitForm(e)}
260284
className="grid h-full max-h-full grid-rows-[2.5rem_1fr_2.5rem] overflow-hidden rounded-md border border-grid-bright"
261285
>
262-
<input type="hidden" name="type" value={"DATETIME"} />
286+
<input type="hidden" name="type" value={"MANUAL"} />
263287
<input
264288
type="hidden"
265289
name="successRedirect"
@@ -313,7 +337,7 @@ function CompleteManualWaitpointForm({ waitpoint }: { waitpoint: { friendlyId: s
313337
}
314338
code={`
315339
await wait.completeToken<YourType>(tokenId,
316-
output
340+
output
317341
);`}
318342
showLineNumbers={false}
319343
/>

0 commit comments

Comments
 (0)