Skip to content

Commit fc25131

Browse files
committed
Merge remote-tracking branch 'origin/main' into coordinator-observability
2 parents 2c716a9 + 4b0f677 commit fc25131

File tree

688 files changed

+3699
-1487
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

688 files changed

+3699
-1487
lines changed

.changeset/config.json

+3-17
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,13 @@
77
}
88
],
99
"commit": false,
10-
"fixed": [
11-
[
12-
"@trigger.dev/*",
13-
"trigger.dev"
14-
]
15-
],
10+
"fixed": [["@trigger.dev/*", "trigger.dev"]],
1611
"linked": [],
1712
"access": "public",
1813
"baseBranch": "main",
1914
"updateInternalDependencies": "patch",
20-
"ignore": [
21-
"webapp",
22-
"emails",
23-
"proxy",
24-
"@trigger.dev/database",
25-
"coordinator",
26-
"docker-provider",
27-
"kubernetes-provider",
28-
"@trigger.dev/otlp-importer"
29-
],
15+
"ignore": ["webapp", "proxy", "coordinator", "docker-provider", "kubernetes-provider"],
3016
"___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": {
3117
"onlyUpdatePeerDependentsWhenOutOfRange": true
3218
}
33-
}
19+
}

.changeset/plenty-spoons-build.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"trigger.dev": patch
3+
"@trigger.dev/core": patch
4+
---
5+
6+
Prettier and more specific errors with links to docs

.github/workflows/unit-tests.yml

+3
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,8 @@ jobs:
2727
- name: 📥 Download deps
2828
run: pnpm install --frozen-lockfile
2929

30+
- name: 📀 Generate Prisma Client
31+
run: pnpm run generate
32+
3033
- name: 🧪 Run Unit Tests
3134
run: pnpm run test

.gitmodules

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
[submodule "packages/otlp-importer/protos"]
2-
path = packages/otlp-importer/protos
1+
[submodule "internal-packages/otlp-importer/protos"]
2+
path = internal-packages/otlp-importer/protos
33
url = https://github.com/open-telemetry/opentelemetry-proto.git

apps/coordinator/src/index.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -493,10 +493,10 @@ class TaskCoordinator {
493493
log.error("Error while waiting for checkpointable state", { error });
494494

495495
if (error instanceof CheckpointReadinessTimeoutError) {
496-
await crashRun({
497-
name: error.name,
498-
message: `Failed to become checkpointable in ${CHECKPOINTABLE_TIMEOUT_SECONDS}s for ${reason}`,
499-
});
496+
logger.error(
497+
`Failed to become checkpointable in ${CHECKPOINTABLE_TIMEOUT_SECONDS}s for ${reason}`,
498+
{ runId: socket.data.runId }
499+
);
500500

501501
return {
502502
success: false,
@@ -585,7 +585,7 @@ class TaskCoordinator {
585585
updateAttemptFriendlyId(executionAck.payload.execution.attempt.id);
586586
updateAttemptNumber(executionAck.payload.execution.attempt.number);
587587
} catch (error) {
588-
log.error("Error", { error });
588+
log.error("READY_FOR_EXECUTION error", { error });
589589

590590
await crashRun({
591591
name: "ReadyForExecutionError",
@@ -625,7 +625,7 @@ class TaskCoordinator {
625625
}
626626

627627
if (!lazyAttempt.success) {
628-
log.error("failed to get lazy attempt payload");
628+
log.error("failed to get lazy attempt payload", { reason: lazyAttempt.reason });
629629

630630
await crashRun({
631631
name: "ReadyForLazyAttemptError",
@@ -647,7 +647,7 @@ class TaskCoordinator {
647647
return;
648648
}
649649

650-
log.error("Error", { error });
650+
log.error("READY_FOR_LAZY_ATTEMPT error", { error });
651651

652652
await crashRun({
653653
name: "ReadyForLazyAttemptError",
@@ -1152,7 +1152,7 @@ class TaskCoordinator {
11521152
});
11531153

11541154
if (!createAttempt?.success) {
1155-
log.debug("no ack while creating attempt");
1155+
log.debug("no ack while creating attempt", { reason: createAttempt?.reason });
11561156
callback({ success: false, reason: createAttempt?.reason });
11571157
return;
11581158
}

apps/kubernetes-provider/src/taskMonitor.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ import { SimpleLogger } from "@trigger.dev/core/v3/apps";
33
import { EXIT_CODE_ALREADY_HANDLED, EXIT_CODE_CHILD_NONZERO } from "@trigger.dev/core/v3/apps";
44
import { setTimeout } from "timers/promises";
55
import PQueue from "p-queue";
6-
import type { Prettify } from "@trigger.dev/core/v3";
6+
import { TaskRunErrorCodes, type Prettify, type TaskRunInternalError } from "@trigger.dev/core/v3";
77

88
type FailureDetails = Prettify<{
99
exitCode: number;
1010
reason: string;
1111
logs: string;
1212
overrideCompletion: boolean;
13+
errorCode: TaskRunInternalError["code"];
1314
}>;
1415

1516
type IndexFailureHandler = (deploymentId: string, details: FailureDetails) => Promise<any>;
@@ -160,18 +161,23 @@ export class TaskMonitor {
160161
let reason = rawReason || "Unknown error";
161162
let logs = rawLogs || "";
162163
let overrideCompletion = false;
164+
let errorCode: TaskRunInternalError["code"] = TaskRunErrorCodes.POD_UNKNOWN_ERROR;
163165

164166
switch (rawReason) {
165167
case "Error":
166168
reason = "Unknown error.";
169+
errorCode = TaskRunErrorCodes.POD_UNKNOWN_ERROR;
167170
break;
168171
case "Evicted":
169172
if (message.startsWith("Pod ephemeral local storage usage")) {
170173
reason = "Storage limit exceeded.";
174+
errorCode = TaskRunErrorCodes.DISK_SPACE_EXCEEDED;
171175
} else if (message) {
172176
reason = `Evicted: ${message}`;
177+
errorCode = TaskRunErrorCodes.POD_EVICTED;
173178
} else {
174179
reason = "Evicted for unknown reason.";
180+
errorCode = TaskRunErrorCodes.POD_EVICTED;
175181
}
176182

177183
if (logs.startsWith("failed to try resolving symlinks")) {
@@ -183,6 +189,7 @@ export class TaskMonitor {
183189
reason = `${
184190
exitCode === EXIT_CODE_CHILD_NONZERO ? "Child process" : "Parent process"
185191
} ran out of memory! Try choosing a machine preset with more memory for this task.`;
192+
errorCode = TaskRunErrorCodes.TASK_PROCESS_OOM_KILLED;
186193
break;
187194
default:
188195
break;
@@ -193,6 +200,7 @@ export class TaskMonitor {
193200
reason,
194201
logs,
195202
overrideCompletion,
203+
errorCode,
196204
} satisfies FailureDetails;
197205

198206
const app = pod.metadata?.labels?.app;

apps/webapp/app/components/runs/v3/RunInspector.tsx

+19-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import { CheckIcon, ClockIcon, CloudArrowDownIcon, QueueListIcon } from "@heroicons/react/20/solid";
22
import { Link } from "@remix-run/react";
3-
import { formatDuration, formatDurationMilliseconds, TaskRunError } from "@trigger.dev/core/v3";
3+
import {
4+
formatDuration,
5+
formatDurationMilliseconds,
6+
TaskRunError,
7+
taskRunErrorEnhancer,
8+
} from "@trigger.dev/core/v3";
49
import { useEffect } from "react";
510
import { useTypedFetcher } from "remix-typedjson";
611
import { ExitIcon } from "~/assets/icons/ExitIcon";
@@ -553,32 +558,39 @@ function RunTimeline({ run }: { run: RawRun }) {
553558
}
554559

555560
function RunError({ error }: { error: TaskRunError }) {
556-
switch (error.type) {
561+
const enhancedError = taskRunErrorEnhancer(error);
562+
563+
switch (enhancedError.type) {
557564
case "STRING_ERROR":
558565
case "CUSTOM_ERROR": {
559566
return (
560567
<div className="flex flex-col gap-2 rounded-sm border border-rose-500/50 px-3 pb-3 pt-2">
561568
<CodeBlock
562569
showCopyButton={false}
563570
showLineNumbers={false}
564-
code={error.raw}
571+
code={enhancedError.raw}
565572
maxLines={20}
566573
/>
567574
</div>
568575
);
569576
}
570577
case "BUILT_IN_ERROR":
571578
case "INTERNAL_ERROR": {
572-
const name = "name" in error ? error.name : error.code;
579+
const name = "name" in enhancedError ? enhancedError.name : enhancedError.code;
573580
return (
574581
<div className="flex flex-col gap-2 rounded-sm border border-rose-500/50 px-3 pb-3 pt-2">
575582
<Header3 className="text-rose-500">{name}</Header3>
576-
{error.message && <Callout variant="error">{error.message}</Callout>}
577-
{error.stackTrace && (
583+
{enhancedError.message && <Callout variant="error">{enhancedError.message}</Callout>}
584+
{enhancedError.link && (
585+
<Callout variant="docs" to={enhancedError.link.href}>
586+
{enhancedError.link.name}
587+
</Callout>
588+
)}
589+
{enhancedError.stackTrace && (
578590
<CodeBlock
579591
showCopyButton={false}
580592
showLineNumbers={false}
581-
code={error.stackTrace}
593+
code={enhancedError.stackTrace}
582594
maxLines={20}
583595
/>
584596
)}

apps/webapp/app/components/runs/v3/SpanEvents.tsx

+12-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
exceptionEventEnhancer,
23
isExceptionSpanEvent,
34
type ExceptionEventProperties,
45
type SpanEvent as OtelSpanEvent,
@@ -64,19 +65,26 @@ export function SpanEventError({
6465
spanEvent: OtelSpanEvent;
6566
exception: ExceptionEventProperties;
6667
}) {
68+
const enhancedException = exceptionEventEnhancer(exception);
69+
6770
return (
6871
<div className="flex flex-col gap-2 rounded-sm border border-rose-500/50 px-3 pb-3 pt-2">
6972
<SpanEventHeader
70-
title={exception.type ?? "Error"}
73+
title={enhancedException.type ?? "Error"}
7174
time={spanEvent.time}
7275
titleClassName="text-rose-500"
7376
/>
74-
{exception.message && <Callout variant="error">{exception.message}</Callout>}
75-
{exception.stacktrace && (
77+
{enhancedException.message && <Callout variant="error">{enhancedException.message}</Callout>}
78+
{enhancedException.link && (
79+
<Callout variant="docs" to={enhancedException.link.href}>
80+
{enhancedException.link.name}
81+
</Callout>
82+
)}
83+
{enhancedException.stacktrace && (
7684
<CodeBlock
7785
showCopyButton={false}
7886
showLineNumbers={false}
79-
code={exception.stacktrace}
87+
code={enhancedException.stacktrace}
8088
maxLines={20}
8189
/>
8290
)}

apps/webapp/app/db.server.ts

+21-47
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,51 @@
1-
import { Prisma, PrismaClient } from "@trigger.dev/database";
1+
import {
2+
Prisma,
3+
PrismaClient,
4+
PrismaClientOrTransaction,
5+
PrismaReplicaClient,
6+
PrismaTransactionClient,
7+
PrismaTransactionOptions,
8+
} from "@trigger.dev/database";
29
import invariant from "tiny-invariant";
310
import { z } from "zod";
411
import { env } from "./env.server";
512
import { logger } from "./services/logger.server";
613
import { isValidDatabaseUrl } from "./utils/db";
714
import { singleton } from "./utils/singleton";
15+
import { $transaction as transac } from "@trigger.dev/database";
816

9-
export type PrismaTransactionClient = Omit<
10-
PrismaClient,
11-
"$connect" | "$disconnect" | "$on" | "$transaction" | "$use" | "$extends"
12-
>;
13-
14-
export type PrismaClientOrTransaction = PrismaClient | PrismaTransactionClient;
15-
16-
function isTransactionClient(prisma: PrismaClientOrTransaction): prisma is PrismaTransactionClient {
17-
return !("$transaction" in prisma);
18-
}
19-
20-
function isPrismaKnownError(error: unknown): error is Prisma.PrismaClientKnownRequestError {
21-
return (
22-
typeof error === "object" && error !== null && "code" in error && typeof error.code === "string"
23-
);
24-
}
25-
26-
export type PrismaTransactionOptions = {
27-
/** The maximum amount of time (in ms) Prisma Client will wait to acquire a transaction from the database. The default value is 2000ms. */
28-
maxWait?: number;
29-
30-
/** The maximum amount of time (in ms) the interactive transaction can run before being canceled and rolled back. The default value is 5000ms. */
31-
timeout?: number;
32-
33-
/** Sets the transaction isolation level. By default this is set to the value currently configured in your database. */
34-
isolationLevel?: Prisma.TransactionIsolationLevel;
35-
36-
swallowPrismaErrors?: boolean;
17+
export type {
18+
PrismaTransactionClient,
19+
PrismaClientOrTransaction,
20+
PrismaTransactionOptions,
21+
PrismaReplicaClient,
3722
};
3823

3924
export async function $transaction<R>(
4025
prisma: PrismaClientOrTransaction,
4126
fn: (prisma: PrismaTransactionClient) => Promise<R>,
4227
options?: PrismaTransactionOptions
4328
): Promise<R | undefined> {
44-
if (isTransactionClient(prisma)) {
45-
return fn(prisma);
46-
}
47-
48-
try {
49-
return await (prisma as PrismaClient).$transaction(fn, options);
50-
} catch (error) {
51-
if (isPrismaKnownError(error)) {
29+
return transac(
30+
prisma,
31+
fn,
32+
(error) => {
5233
logger.error("prisma.$transaction error", {
5334
code: error.code,
5435
meta: error.meta,
5536
stack: error.stack,
5637
message: error.message,
5738
name: error.name,
5839
});
59-
60-
if (options?.swallowPrismaErrors) {
61-
return;
62-
}
63-
}
64-
65-
throw error;
66-
}
40+
},
41+
options
42+
);
6743
}
6844

6945
export { Prisma };
7046

7147
export const prisma = singleton("prisma", getClient);
7248

73-
export type PrismaReplicaClient = Omit<PrismaClient, "$transaction">;
74-
7549
export const $replica: PrismaReplicaClient = singleton(
7650
"replica",
7751
() => getReplicaClient() ?? prisma

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.environments/ConfigureEndpointSheet.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { Paragraph } from "~/components/primitives/Paragraph";
2222
import { Sheet, SheetBody, SheetContent, SheetHeader } from "~/components/primitives/Sheet";
2323
import { ClientEndpoint } from "~/presenters/EnvironmentsPresenter.server";
2424
import { endpointStreamingPath } from "~/utils/pathBuilder";
25-
import { EndpointIndexStatus, RuntimeEnvironmentType } from "../../../../../packages/database/src";
25+
import { EndpointIndexStatus, RuntimeEnvironmentType } from "@trigger.dev/database";
2626
import { bodySchema } from "../resources.environments.$environmentParam.endpoint";
2727

2828
type ConfigureEndpointSheetProps = {

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import {
3939
projectEnvironmentsStreamingPath,
4040
} from "~/utils/pathBuilder";
4141
import { requestUrl } from "~/utils/requestUrl.server";
42-
import { RuntimeEnvironmentType } from "../../../../../packages/database/src";
42+
import { RuntimeEnvironmentType } from "@trigger.dev/database";
4343
import { ConfigureEndpointSheet } from "./ConfigureEndpointSheet";
4444
import { FirstEndpointSheet } from "./FirstEndpointSheet";
4545
import { BookOpenIcon } from "@heroicons/react/20/solid";

0 commit comments

Comments
 (0)