Skip to content

Commit 9a80f47

Browse files
committed
More run metadata stuff
- Add metadata to testing - Make using metadata outside of runs a no-op - Add docs
1 parent 61c8bc8 commit 9a80f47

File tree

17 files changed

+462
-84
lines changed

17 files changed

+462
-84
lines changed

.changeset/tasty-rats-rhyme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
"@trigger.dev/core": patch
44
---
55

6-
Add Run metadata to allow for storing up to 8KB of data on a run and update it during the run
6+
Add Run metadata to allow for storing up to 4KB of data on a run and update it during the run

apps/webapp/app/components/code/JSONEditor.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,9 @@ export function JSONEditor(opts: JSONEditorProps) {
112112
return (
113113
<div
114114
className={cn(
115-
opts.className,
116115
"grid",
117-
showButtons ? "grid-rows-[2.5rem_1fr]" : "grid-rows-[1fr]"
116+
showButtons ? "grid-rows-[2.5rem_1fr]" : "grid-rows-[1fr]",
117+
opts.className
118118
)}
119119
>
120120
{showButtons && (

apps/webapp/app/components/primitives/Tabs.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ export function TabButton({
9797
return (
9898
<button
9999
className={cn("group flex flex-col items-center pt-1", props.className)}
100+
type="button"
100101
ref={ref}
101102
{...props}
102103
>

apps/webapp/app/env.server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ const EnvironmentSchema = z.object({
212212
MAXIMUM_TRACE_SUMMARY_VIEW_COUNT: z.coerce.number().int().default(25_000),
213213
TASK_PAYLOAD_OFFLOAD_THRESHOLD: z.coerce.number().int().default(524_288), // 512KB
214214
TASK_PAYLOAD_MAXIMUM_SIZE: z.coerce.number().int().default(3_145_728), // 3MB
215-
TASK_RUN_METADATA_MAXIMUM_SIZE: z.coerce.number().int().default(8_000), // 8KB
215+
TASK_RUN_METADATA_MAXIMUM_SIZE: z.coerce.number().int().default(4_096), // 4KB
216216
});
217217

218218
export type Environment = z.infer<typeof EnvironmentSchema>;

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

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
import { ScheduledTaskPayload, parsePacket, prettyPrintPacket } from "@trigger.dev/core/v3";
2-
import {
3-
RuntimeEnvironmentType,
4-
TaskRunAttemptStatus,
5-
TaskRunStatus,
6-
TaskTriggerSource,
7-
} from "@trigger.dev/database";
8-
import { sqlDatabaseSchema, PrismaClient, prisma } from "~/db.server";
2+
import { RuntimeEnvironmentType, TaskRunStatus } from "@trigger.dev/database";
3+
import { PrismaClient, prisma, sqlDatabaseSchema } from "~/db.server";
94
import { getTimezones } from "~/utils/timezones.server";
105
import { getUsername } from "~/utils/username";
116

@@ -51,6 +46,8 @@ type RawRun = {
5146
payload: string;
5247
payloadType: string;
5348
runtimeEnvironmentId: string;
49+
metadata?: string;
50+
metadataType?: string;
5451
};
5552

5653
export type StandardRun = Omit<RawRun, "number"> & {
@@ -131,6 +128,8 @@ export class TestTaskPresenter {
131128
taskr.status,
132129
taskr.payload,
133130
taskr."payloadType",
131+
taskr.metadata,
132+
taskr."metadataType",
134133
taskr."runtimeEnvironmentId"
135134
FROM
136135
taskruns AS taskr
@@ -166,6 +165,9 @@ export class TestTaskPresenter {
166165
...r,
167166
number,
168167
payload: await prettyPrintPacket(r.payload, r.payloadType),
168+
metadata: r.metadata
169+
? await prettyPrintPacket(r.metadata, r.metadataType)
170+
: undefined,
169171
};
170172
})
171173
),

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.v3.$projectParam.test.tasks.$taskParam/route.tsx

Lines changed: 97 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@ import {
2727
ResizablePanelGroup,
2828
} from "~/components/primitives/Resizable";
2929
import { Select } from "~/components/primitives/Select";
30+
import { TabButton, TabContainer } from "~/components/primitives/Tabs";
3031
import { TextLink } from "~/components/primitives/TextLink";
3132
import { TaskRunStatusCombo } from "~/components/runs/v3/TaskRunStatus";
3233
import { TimezoneList } from "~/components/scheduled/timezones";
34+
import { useSearchParams } from "~/hooks/useSearchParam";
3335
import { redirectBackWithErrorMessage, redirectWithSuccessMessage } from "~/models/message.server";
3436
import {
3537
ScheduledRun,
@@ -39,6 +41,7 @@ import {
3941
} from "~/presenters/v3/TestTaskPresenter.server";
4042
import { logger } from "~/services/logger.server";
4143
import { requireUserId } from "~/services/session.server";
44+
import { cn } from "~/utils/cn";
4245
import { docsPath, v3RunSpanPath, v3TaskParamsSchema } from "~/utils/pathBuilder";
4346
import { TestTaskService } from "~/v3/services/testTask.server";
4447
import { OutOfEntitlementError } from "~/v3/services/triggerTask.server";
@@ -129,27 +132,44 @@ export default function Page() {
129132
const startingJson = "{\n\n}";
130133

131134
function StandardTaskForm({ task, runs }: { task: TestTask["task"]; runs: StandardRun[] }) {
135+
const { value, replace } = useSearchParams();
136+
const tab = value("tab");
137+
132138
//form submission
133139
const submit = useSubmit();
134140
const lastSubmission = useActionData();
135141

136142
//recent runs
137143
const [selectedCodeSampleId, setSelectedCodeSampleId] = useState(runs.at(0)?.id);
138-
const selectedCodeSample = runs.find((r) => r.id === selectedCodeSampleId)?.payload;
144+
const selectedCodeSample = runs.find((r) => r.id === selectedCodeSampleId);
145+
const selectedCodeSamplePayload = selectedCodeSample?.payload;
146+
const selectedCodeSampleMetadata = selectedCodeSample?.metadata;
139147

140-
const [defaultJson, setDefaultJson] = useState<string>(selectedCodeSample ?? startingJson);
141-
const setCode = useCallback((code: string) => {
142-
setDefaultJson(code);
148+
const [defaultPayloadJson, setDefaultPayloadJson] = useState<string>(
149+
selectedCodeSamplePayload ?? startingJson
150+
);
151+
const setPayload = useCallback((code: string) => {
152+
setDefaultPayloadJson(code);
143153
}, []);
144154

145-
const currentJson = useRef<string>(defaultJson);
155+
const currentPayloadJson = useRef<string>(defaultPayloadJson);
156+
157+
const [defaultMetadataJson, setDefaultMetadataJson] = useState<string>(
158+
selectedCodeSampleMetadata ?? "{}"
159+
);
160+
const setMetadata = useCallback((code: string) => {
161+
setDefaultMetadataJson(code);
162+
}, []);
163+
164+
const currentMetadataJson = useRef<string>(defaultMetadataJson);
146165

147166
const submitForm = useCallback(
148167
(e: React.FormEvent<HTMLFormElement>) => {
149168
submit(
150169
{
151170
triggerSource: "STANDARD",
152-
payload: currentJson.current,
171+
payload: currentPayloadJson.current,
172+
metadata: currentMetadataJson.current,
153173
taskIdentifier: task.taskIdentifier,
154174
environmentId: task.environment.id,
155175
},
@@ -160,7 +180,7 @@ function StandardTaskForm({ task, runs }: { task: TestTask["task"]; runs: Standa
160180
);
161181
e.preventDefault();
162182
},
163-
[currentJson]
183+
[currentPayloadJson, currentMetadataJson]
164184
);
165185

166186
const [form, { environmentId, payload }] = useForm({
@@ -183,28 +203,73 @@ function StandardTaskForm({ task, runs }: { task: TestTask["task"]; runs: Standa
183203
<ResizablePanelGroup orientation="horizontal">
184204
<ResizablePanel id="test-task-main" min="100px" default="60%">
185205
<div className="h-full bg-charcoal-900">
186-
<JSONEditor
187-
defaultValue={defaultJson}
188-
readOnly={false}
189-
basicSetup
190-
onChange={(v) => {
191-
currentJson.current = v;
192-
193-
//deselect the example if it's been edited
194-
if (selectedCodeSampleId) {
195-
if (v !== selectedCodeSample) {
196-
setDefaultJson(v);
197-
setSelectedCodeSampleId(undefined);
206+
<TabContainer className="px-3 pt-2">
207+
<TabButton
208+
isActive={!tab || tab === "payload"}
209+
layoutId="test-editor"
210+
onClick={() => {
211+
replace({ tab: "payload" });
212+
}}
213+
>
214+
Payload
215+
</TabButton>
216+
217+
<TabButton
218+
isActive={tab === "metadata"}
219+
layoutId="test-editor"
220+
onClick={() => {
221+
replace({ tab: "metadata" });
222+
}}
223+
>
224+
Metadata
225+
</TabButton>
226+
</TabContainer>
227+
<div>
228+
<JSONEditor
229+
defaultValue={defaultPayloadJson}
230+
readOnly={false}
231+
basicSetup
232+
onChange={(v) => {
233+
currentPayloadJson.current = v;
234+
235+
//deselect the example if it's been edited
236+
if (selectedCodeSampleId) {
237+
if (v !== selectedCodeSamplePayload) {
238+
setDefaultPayloadJson(v);
239+
setSelectedCodeSampleId(undefined);
240+
}
198241
}
199-
}
200-
}}
201-
height="100%"
202-
min-height="100%"
203-
max-height="100%"
204-
autoFocus
205-
placeholder="Use your schema to enter valid JSON or add one of the recent payloads then click 'Run test'"
206-
className="h-full"
207-
/>
242+
}}
243+
height="100%"
244+
min-height="100%"
245+
max-height="100%"
246+
autoFocus
247+
placeholder="{ }"
248+
className={cn("h-full", tab === "metadata" && "hidden")}
249+
/>
250+
<JSONEditor
251+
defaultValue={defaultMetadataJson}
252+
readOnly={false}
253+
basicSetup
254+
onChange={(v) => {
255+
currentMetadataJson.current = v;
256+
257+
//deselect the example if it's been edited
258+
if (selectedCodeSampleId) {
259+
if (v !== selectedCodeSampleMetadata) {
260+
setDefaultMetadataJson(v);
261+
setSelectedCodeSampleId(undefined);
262+
}
263+
}
264+
}}
265+
height="100%"
266+
min-height="100%"
267+
max-height="100%"
268+
autoFocus
269+
placeholder=""
270+
className={cn("h-full", tab !== "metadata" && "hidden")}
271+
/>
272+
</div>
208273
</div>
209274
</ResizablePanel>
210275
<ResizableHandle id="test-task-handle" />
@@ -213,9 +278,10 @@ function StandardTaskForm({ task, runs }: { task: TestTask["task"]; runs: Standa
213278
runs={runs}
214279
selectedId={selectedCodeSampleId}
215280
onSelected={(id) => {
216-
const payload = runs.find((r) => r.id === id)?.payload;
217-
if (!payload) return;
218-
setCode(payload);
281+
const run = runs.find((r) => r.id === id);
282+
if (!run) return;
283+
setPayload(run.payload);
284+
run.metadata && setMetadata(run.metadata);
219285
setSelectedCodeSampleId(id);
220286
}}
221287
/>

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.v3.$projectParam.test/route.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,13 @@ export default function Page() {
7575
const navigation = useNavigation();
7676

7777
const location = useLocation();
78+
const locationSearchParams = new URLSearchParams(location.search);
79+
const navigationSearchParams = new URLSearchParams(navigation.location?.search);
80+
7881
const isLoadingTasks =
79-
navigation.state === "loading" && navigation.location.pathname === location.pathname;
82+
navigation.state === "loading" &&
83+
navigation.location.pathname === location.pathname &&
84+
navigationSearchParams.get("environment") !== locationSearchParams.get("environment");
8085

8186
return (
8287
<PageContainer>

apps/webapp/app/v3/services/testTask.server.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export class TestTaskService extends BaseService {
1919
payload: data.payload,
2020
options: {
2121
test: true,
22+
metadata: data.metadata,
2223
},
2324
});
2425
case "SCHEDULED": {

apps/webapp/app/v3/testTask.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,26 @@ export const TestTaskData = z
1111
} catch (e) {
1212
console.log("parsing error", e);
1313

14+
if (e instanceof Error) {
15+
ctx.addIssue({
16+
code: z.ZodIssueCode.custom,
17+
message: e.message,
18+
});
19+
} else {
20+
ctx.addIssue({
21+
code: z.ZodIssueCode.custom,
22+
message: "This is invalid JSON",
23+
});
24+
}
25+
}
26+
}),
27+
metadata: z.string().transform((metadata, ctx) => {
28+
try {
29+
const data = JSON.parse(metadata);
30+
return data as any;
31+
} catch (e) {
32+
console.log("parsing error", e);
33+
1434
if (e instanceof Error) {
1535
ctx.addIssue({
1636
code: z.ZodIssueCode.custom,

docs/images/run-metadata.png

666 KB
Loading

0 commit comments

Comments
 (0)