Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
3eea949
Upgrade graphile-worker
nicktrn Oct 2, 2023
e4630f6
CronItem.pattern to match
nicktrn Oct 2, 2023
8e887af
Update graphile job schema
nicktrn Oct 2, 2023
0400e02
Add FAIL_LOCKED_JOBS_ON_STARTUP
nicktrn Oct 2, 2023
6440e30
Add to .env.example
nicktrn Oct 2, 2023
e3c9559
Detect migration errors
nicktrn Oct 2, 2023
25d6478
Rename migration env var
nicktrn Oct 2, 2023
00eade2
Improve migration helper, don't require restart
nicktrn Oct 2, 2023
8efb0a5
Remove restart comment for now
nicktrn Oct 3, 2023
d20a49e
Add migration docs
nicktrn Oct 3, 2023
aab2c8b
Link to migration docs
nicktrn Oct 3, 2023
b45f9fb
Lowercase
nicktrn Oct 3, 2023
6c3921b
Merge branch 'main' into worker-upgrade
nicktrn Oct 3, 2023
4f1c52f
Merge branch 'main' into worker-upgrade
nicktrn Oct 16, 2023
86d6343
Fix merge
nicktrn Oct 16, 2023
70af76a
Send batched events
nicktrn Oct 5, 2023
21a3c47
io.sendEvent props
nicktrn Oct 5, 2023
11be807
JSON editor cursor position and empty objects
nicktrn Oct 19, 2023
d934de4
Fix batched worker enqueue
nicktrn Oct 19, 2023
cb43a0d
Airtable error handling
nicktrn Oct 19, 2023
7dbc93d
New DB columns
nicktrn Oct 19, 2023
43b6462
Add db push script
nicktrn Oct 19, 2023
cb65469
Add batching options to SDK
nicktrn Oct 19, 2023
c4141dc
Batch without touching prior JobRun data
nicktrn Oct 19, 2023
0a657c4
Fix UI
nicktrn Oct 19, 2023
bcb8e25
Airtable provisional webhook tests
nicktrn Oct 19, 2023
1164260
Update static trigger metadata
nicktrn Oct 19, 2023
23ac303
Better tests for delivery time preservation
nicktrn Oct 19, 2023
dc3a8e0
Merge branch 'main' into features/batched-events
nicktrn Oct 19, 2023
f3f51a4
Update lockfile
nicktrn Oct 19, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ NODE_ENV=development
# FROM_EMAIL=
# REPLY_TO_EMAIL=

# Required for upgrading graphile-worker to v0.14 when graceful shutdown is impossible or impractical.
# FAIL_LOCKED_JOBS_FOR_MIGRATION=true

# CLOUD VARIABLES
POSTHOG_PROJECT_KEY=
PLAIN_API_KEY=
Expand Down
33 changes: 29 additions & 4 deletions apps/webapp/app/components/code/JSONEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { json as jsonLang } from "@codemirror/lang-json";
import type { ViewUpdate } from "@codemirror/view";
import type { Text } from "@codemirror/state";
import { CheckIcon, ClipboardIcon } from "@heroicons/react/20/solid";
import type { ReactCodeMirrorProps, UseCodeMirror } from "@uiw/react-codemirror";
import { useCodeMirror } from "@uiw/react-codemirror";
Expand Down Expand Up @@ -68,6 +69,7 @@ export function JSONEditor(opts: JSONEditorProps) {
theme: darkTheme(),
indentWithTab: false,
basicSetup,
selection: getDefaultSelection(defaultValue),
onChange,
onUpdate,
};
Expand All @@ -83,10 +85,16 @@ export function JSONEditor(opts: JSONEditorProps) {
//if the defaultValue changes update the editor
useEffect(() => {
if (view !== undefined) {
if (view.state.doc.toString() === defaultValue) return;
view.dispatch({
changes: { from: 0, to: view.state.doc.length, insert: defaultValue },
});
if (view.state.doc.toString() !== defaultValue) {
view.dispatch({
changes: { from: 0, to: view.state.doc.length, insert: defaultValue },
selection: getDefaultSelection(defaultValue),
});
} else {
view.dispatch({
selection: getDefaultSelection(defaultValue),
});
}
}
}, [defaultValue, view]);

Expand Down Expand Up @@ -150,3 +158,20 @@ export function JSONEditor(opts: JSONEditorProps) {
</div>
);
}

function isMultiline(content: string | Text) {
if (typeof content === "string") {
return content.includes("\n");
} else {
return content.lines > 1;
}
}

/** For multiline content, gets end of penultimate line. Otherwise, position `0`. */
function getDefaultSelection(content: string | Text) {
if (!isMultiline(content)) {
return { anchor: 0 };
} else {
return { anchor: content.length > 2 ? content.length - 2 : 0 };
}
}
4 changes: 3 additions & 1 deletion apps/webapp/app/components/run/TriggerDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,19 @@ import { DisplayProperty } from "@trigger.dev/core";

export function TriggerDetail({
trigger,
payload,
event,
properties,
}: {
trigger: DetailedEvent;
payload: string;
event: {
title: string;
icon: string;
};
properties: DisplayProperty[];
}) {
const { id, name, payload, context, timestamp, deliveredAt } = trigger;
const { id, name, context, timestamp, deliveredAt } = trigger;

return (
<RunPanel selected={false}>
Expand Down
7 changes: 7 additions & 0 deletions apps/webapp/app/entry.server.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,5 +164,12 @@ function logError(error: unknown, request?: Request) {
);
}
}

console.error(error);

if (error instanceof Error && error.message === "division by zero") {
console.log("⚠️ possible graphile-worker migration issue detected");
console.log("⚠️ set FAIL_LOCKED_JOBS_FOR_MIGRATION=true if this persists");
console.log("⚠️ see: https://trigger.dev/docs/documentation/guides/self-hosting/graphile-migration");
}
}
1 change: 1 addition & 0 deletions apps/webapp/app/env.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const EnvironmentSchema = z.object({
WORKER_ENABLED: z.string().default("true"),
EXECUTION_WORKER_ENABLED: z.string().default("true"),
GRACEFUL_SHUTDOWN_TIMEOUT: z.coerce.number().int().default(60000),
FAIL_LOCKED_JOBS_FOR_MIGRATION: z.string().default("false"),
});

export type Environment = z.infer<typeof EnvironmentSchema>;
Expand Down
14 changes: 7 additions & 7 deletions apps/webapp/app/platform/zodWorker.server.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type {
CronItem,
CronItemOptions,
Job as GraphileJob,
DbJob as GraphileJob,
Runner as GraphileRunner,
JobHelpers,
RunnerOptions,
Expand Down Expand Up @@ -29,8 +29,8 @@ const RawCronPayloadSchema = z.object({

const GraphileJobSchema = z.object({
id: z.coerce.string(),
queue_name: z.string().nullable(),
task_identifier: z.string(),
job_queue_id: z.number().nullable(),
task_id: z.number(),
payload: z.unknown(),
priority: z.number(),
run_at: z.coerce.date(),
Expand Down Expand Up @@ -67,7 +67,7 @@ type RecurringTaskPayload = {

export type ZodRecurringTasks = {
[key: string]: {
pattern: string;
match: string;
options?: CronItemOptions;
handler: (payload: RecurringTaskPayload, job: GraphileJob) => Promise<void>;
};
Expand Down Expand Up @@ -411,7 +411,7 @@ export class ZodWorker<TMessageCatalog extends MessageCatalogSchema> {

if (this.#cleanup) {
cronItems.push({
pattern: this.#cleanup.frequencyExpression,
match: this.#cleanup.frequencyExpression,
identifier: CLEANUP_TASK_NAME,
task: CLEANUP_TASK_NAME,
options: this.#cleanup.taskOptions,
Expand All @@ -420,7 +420,7 @@ export class ZodWorker<TMessageCatalog extends MessageCatalogSchema> {

if (this.#reporter) {
cronItems.push({
pattern: "50 * * * *", // Every hour at 50 minutes past the hour
match: "50 * * * *", // Every hour at 50 minutes past the hour
identifier: REPORTER_TASK_NAME,
task: REPORTER_TASK_NAME,
});
Expand All @@ -432,7 +432,7 @@ export class ZodWorker<TMessageCatalog extends MessageCatalogSchema> {

for (const [key, task] of Object.entries(this.#recurringTasks)) {
const cronItem: CronItem = {
pattern: task.pattern,
match: task.match,
identifier: key,
task: key,
options: task.options,
Expand Down
2 changes: 2 additions & 0 deletions apps/webapp/app/presenters/RunPresenter.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export class RunPresenter {
slug: run.environment.slug,
},
event: this.#prepareEventData(run.event),
payload: run.payload,
tasks,
runConnections: run.runConnections,
missingConnections: run.missingConnections,
Expand All @@ -104,6 +105,7 @@ export class RunPresenter {
query({ id, userId }: RunOptions) {
return this.#prismaClient.jobRun.findFirst({
select: {
payload: true,
id: true,
number: true,
status: true,
Expand Down
35 changes: 26 additions & 9 deletions apps/webapp/app/presenters/TestJobPresenter.server.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { User } from "@trigger.dev/database";
import { Prisma, User } from "@trigger.dev/database";
import { replacements } from "@trigger.dev/core";
import { PrismaClient, prisma } from "~/db.server";
import { Job } from "~/models/job.server";
Expand Down Expand Up @@ -74,6 +74,7 @@ export class TestJobPresenter {
createdAt: true,
number: true,
status: true,
payload: true,
event: {
select: {
payload: true,
Expand Down Expand Up @@ -111,7 +112,7 @@ export class TestJobPresenter {
alias.version.examples.map((example) => ({
...example,
icon: example.icon ?? undefined,
payload: example.payload ? JSON.stringify(example.payload, exampleReplacer, 2) : undefined,
payload: prettyJsonValue(example.payload, exampleReplacer),
}))
);

Expand All @@ -127,13 +128,16 @@ export class TestJobPresenter {
),
})),
examples,
runs: job.runs.map((r) => ({
id: r.id,
number: r.number,
status: r.status,
created: r.createdAt,
payload: r.event.payload ? JSON.stringify(r.event.payload, null, 2) : undefined,
})),
runs: job.runs.map((r) => {
const payload = r.payload ?? r.event.payload;
return {
id: r.id,
number: r.number,
status: r.status,
created: r.createdAt,
payload: prettyJsonValue(payload),
};
}),
};
}
}
Expand All @@ -153,3 +157,16 @@ function exampleReplacer(key: string, value: any) {

return value;
}

function prettyJsonValue(
value: Prisma.JsonValue,
replacer?: (key: string, value: any) => any,
space = 2
) {
if (value === null) {
return;
}

const pretty = JSON.stringify(value, replacer, space);
return pretty === "{}" ? "{\n \n}" : pretty;
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,14 @@ export default function Page() {
const job = useJob();
const run = useRun();

return <TriggerDetail trigger={trigger} event={job.event} properties={run.properties} />;
const payload = run.payload !== null ? JSON.stringify(run.payload, null, 2) : trigger.payload;

return (
<TriggerDetail
trigger={trigger}
payload={payload}
event={job.event}
properties={run.properties}
/>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ export const handle: Handle = {
breadcrumb: (match) => <BreadcrumbLink to={trimTrailingSlash(match.pathname)} title="Test" />,
};

const startingJson = "{\n\n}";
const startingJson = "{\n \n}";

export default function Page() {
const { environments, runs, examples } = useTypedLoaderData<typeof loader>();
Expand Down Expand Up @@ -202,7 +202,6 @@ export default function Page() {
//deselect the example if it's been edited
if (selectedCodeSampleId) {
if (v !== selectedCodeSample) {
setDefaultJson(v);
setSelectedCodeSampleId(undefined);
}
}
Expand Down
Loading