Skip to content

Commit 203e002

Browse files
committed
Add runs.retrieve management API method to get info about a run by run ID
1 parent 1670c4c commit 203e002

File tree

11 files changed

+511
-26
lines changed

11 files changed

+511
-26
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@trigger.dev/sdk": patch
3+
"@trigger.dev/core": patch
4+
---
5+
6+
Add runs.retrieve management API method to get info about a run by run ID
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import { AttemptStatus, RetrieveRunResponse, RunStatus, logger } from "@trigger.dev/core/v3";
2+
import { TaskRunAttemptStatus, TaskRunStatus } from "@trigger.dev/database";
3+
import assertNever from "assert-never";
4+
import { AuthenticatedEnvironment } from "~/services/apiAuth.server";
5+
import { BasePresenter } from "./basePresenter.server";
6+
7+
export class ApiRetrieveRunPresenter extends BasePresenter {
8+
public async call(
9+
friendlyId: string,
10+
env: AuthenticatedEnvironment,
11+
showSecretDetails: boolean
12+
): Promise<RetrieveRunResponse | undefined> {
13+
return this.traceWithEnv("call", env, async (span) => {
14+
const taskRun = await this._prisma.taskRun.findUnique({
15+
where: {
16+
friendlyId,
17+
runtimeEnvironmentId: env.id,
18+
},
19+
include: {
20+
attempts: {
21+
orderBy: {
22+
createdAt: "desc",
23+
},
24+
},
25+
lockedToVersion: true,
26+
},
27+
});
28+
29+
if (!taskRun) {
30+
logger.debug("Task run not found", { friendlyId, envId: env.id });
31+
32+
return undefined;
33+
}
34+
35+
return {
36+
id: taskRun.friendlyId,
37+
status: ApiRetrieveRunPresenter.apiStatusFromRunStatus(taskRun.status),
38+
taskIdentifier: taskRun.taskIdentifier,
39+
idempotencyKey: taskRun.idempotencyKey ?? undefined,
40+
version: taskRun.lockedToVersion ? taskRun.lockedToVersion.version : undefined,
41+
createdAt: taskRun.createdAt ?? undefined,
42+
updatedAt: taskRun.updatedAt ?? undefined,
43+
attempts: !showSecretDetails
44+
? []
45+
: taskRun.attempts.map((a) => ({
46+
id: a.friendlyId,
47+
status: ApiRetrieveRunPresenter.apiStatusFromAttemptStatus(a.status),
48+
createdAt: a.createdAt ?? undefined,
49+
updatedAt: a.updatedAt ?? undefined,
50+
startedAt: a.startedAt ?? undefined,
51+
completedAt: a.completedAt ?? undefined,
52+
})),
53+
};
54+
});
55+
}
56+
57+
static apiStatusFromRunStatus(status: TaskRunStatus): RunStatus {
58+
switch (status) {
59+
case "WAITING_FOR_DEPLOY":
60+
case "PENDING": {
61+
return "PENDING";
62+
}
63+
case "RETRYING_AFTER_FAILURE":
64+
case "EXECUTING": {
65+
return "EXECUTING";
66+
}
67+
case "WAITING_TO_RESUME":
68+
case "PAUSED": {
69+
return "PAUSED";
70+
}
71+
case "CANCELED": {
72+
return "CANCELED";
73+
}
74+
case "COMPLETED_SUCCESSFULLY": {
75+
return "COMPLETED";
76+
}
77+
case "SYSTEM_FAILURE":
78+
case "INTERRUPTED":
79+
case "CRASHED":
80+
case "COMPLETED_WITH_ERRORS": {
81+
return "FAILED";
82+
}
83+
default: {
84+
assertNever(status);
85+
}
86+
}
87+
}
88+
89+
static apiStatusFromAttemptStatus(status: TaskRunAttemptStatus): AttemptStatus {
90+
switch (status) {
91+
case "PENDING": {
92+
return "PENDING";
93+
}
94+
case "PAUSED": {
95+
return "PAUSED";
96+
}
97+
case "EXECUTING": {
98+
return "EXECUTING";
99+
}
100+
case "COMPLETED": {
101+
return "COMPLETED";
102+
}
103+
case "FAILED": {
104+
return "FAILED";
105+
}
106+
case "CANCELED": {
107+
return "CANCELED";
108+
}
109+
default: {
110+
assertNever(status);
111+
}
112+
}
113+
}
114+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import type { LoaderFunctionArgs } from "@remix-run/server-runtime";
2+
import { json } from "@remix-run/server-runtime";
3+
import { z } from "zod";
4+
import { ApiRetrieveRunPresenter } from "~/presenters/v3/ApiRetrieveRunPresenter.server";
5+
import { authenticateApiRequest } from "~/services/apiAuth.server";
6+
import { apiCors } from "~/utils/apiCors";
7+
8+
const ParamsSchema = z.object({
9+
runId: z.string(),
10+
});
11+
12+
export async function loader({ request, params }: LoaderFunctionArgs) {
13+
if (request.method.toUpperCase() === "OPTIONS") {
14+
return apiCors(request, json({}));
15+
}
16+
17+
const authenticationResult = await authenticateApiRequest(request, {
18+
allowPublicKey: true,
19+
});
20+
if (!authenticationResult) {
21+
return apiCors(request, json({ error: "Invalid or Missing API key" }, { status: 401 }));
22+
}
23+
24+
const authenticatedEnv = authenticationResult.environment;
25+
26+
const parsed = ParamsSchema.safeParse(params);
27+
28+
if (!parsed.success) {
29+
return apiCors(request, json({ error: "Invalid or missing runId" }, { status: 400 }));
30+
}
31+
32+
const { runId } = parsed.data;
33+
34+
const showSecretDetails = authenticationResult.type === "PRIVATE";
35+
36+
const presenter = new ApiRetrieveRunPresenter();
37+
const result = await presenter.call(runId, authenticatedEnv, showSecretDetails);
38+
39+
if (!result) {
40+
return apiCors(request, json({ error: "Run not found" }, { status: 404 }));
41+
}
42+
43+
return apiCors(request, json(result));
44+
}

docs/mint.json

Lines changed: 71 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
{
22
"$schema": "https://mintlify.com/schema.json",
33
"name": "Trigger.dev",
4-
"openapi": ["/openapi.yml", "/v3-openapi.json"],
5-
"versions": ["v3 (Developer Preview)", "v2"],
4+
"openapi": [
5+
"/openapi.yml",
6+
"/v3-openapi.json"
7+
],
8+
"versions": [
9+
"v3 (Developer Preview)",
10+
"v2"
11+
],
612
"logo": {
713
"dark": "/logo/dark.png",
814
"light": "/logo/light.png",
@@ -90,7 +96,9 @@
9096
{
9197
"group": "",
9298
"version": "v3 (Developer Preview)",
93-
"pages": ["v3/introduction"]
99+
"pages": [
100+
"v3/introduction"
101+
]
94102
},
95103
{
96104
"group": "Getting Started",
@@ -113,15 +121,23 @@
113121
"v3/apikeys",
114122
{
115123
"group": "Task types",
116-
"pages": ["v3/tasks-regular", "v3/tasks-scheduled", "v3/tasks-zod", "v3/tasks-webhooks"]
124+
"pages": [
125+
"v3/tasks-regular",
126+
"v3/tasks-scheduled",
127+
"v3/tasks-zod",
128+
"v3/tasks-webhooks"
129+
]
117130
},
118131
"v3/trigger-config"
119132
]
120133
},
121134
{
122135
"group": "Development",
123136
"version": "v3 (Developer Preview)",
124-
"pages": ["v3/cli-dev", "v3/run-tests"]
137+
"pages": [
138+
"v3/cli-dev",
139+
"v3/run-tests"
140+
]
125141
},
126142
{
127143
"group": "Deployment",
@@ -132,7 +148,9 @@
132148
"v3/github-actions",
133149
{
134150
"group": "Deployment integrations",
135-
"pages": ["v3/vercel-integration"]
151+
"pages": [
152+
"v3/vercel-integration"
153+
]
136154
}
137155
]
138156
},
@@ -208,7 +226,9 @@
208226
},
209227
{
210228
"group": "Objects",
211-
"pages": ["v3/reference-context"]
229+
"pages": [
230+
"v3/reference-context"
231+
]
212232
},
213233
{
214234
"group": "CLI",
@@ -226,9 +246,7 @@
226246
{
227247
"group": "Runs API",
228248
"pages": [
229-
"v3/management-start-run",
230-
"v3/management-get-run",
231-
"v3/management-get-runs",
249+
"v3/management-retrieve-run",
232250
"v3/management-replay-run",
233251
"v3/management-cancel-run"
234252
]
@@ -259,7 +277,11 @@
259277
{
260278
"group": "Open source",
261279
"version": "v3 (Developer Preview)",
262-
"pages": ["v3/github-repo", "v3/open-source-self-hosting", "v3/open-source-contributing"]
280+
"pages": [
281+
"v3/github-repo",
282+
"v3/open-source-self-hosting",
283+
"v3/open-source-contributing"
284+
]
263285
},
264286
{
265287
"group": "Help",
@@ -460,7 +482,10 @@
460482
"pages": [
461483
{
462484
"group": "Airtable",
463-
"pages": ["integrations/apis/airtable", "integrations/apis/airtable-tasks"]
485+
"pages": [
486+
"integrations/apis/airtable",
487+
"integrations/apis/airtable-tasks"
488+
]
464489
},
465490
{
466491
"group": "GitHub",
@@ -486,16 +511,25 @@
486511
},
487512
{
488513
"group": "Plain",
489-
"pages": ["integrations/apis/plain", "integrations/apis/plain-tasks"]
514+
"pages": [
515+
"integrations/apis/plain",
516+
"integrations/apis/plain-tasks"
517+
]
490518
},
491519
"integrations/apis/replicate",
492520
{
493521
"group": "SendGrid",
494-
"pages": ["integrations/apis/sendgrid", "integrations/apis/sendgrid-tasks"]
522+
"pages": [
523+
"integrations/apis/sendgrid",
524+
"integrations/apis/sendgrid-tasks"
525+
]
495526
},
496527
{
497528
"group": "Resend",
498-
"pages": ["integrations/apis/resend", "integrations/apis/resend-tasks"]
529+
"pages": [
530+
"integrations/apis/resend",
531+
"integrations/apis/resend-tasks"
532+
]
499533
},
500534
{
501535
"group": "Shopify",
@@ -507,7 +541,10 @@
507541
},
508542
{
509543
"group": "Slack",
510-
"pages": ["integrations/apis/slack", "integrations/apis/slack-tasks"]
544+
"pages": [
545+
"integrations/apis/slack",
546+
"integrations/apis/slack-tasks"
547+
]
511548
},
512549
"integrations/apis/stripe",
513550
{
@@ -532,7 +569,9 @@
532569
"sdk/triggerclient/constructor",
533570
{
534571
"group": "Instance properties",
535-
"pages": ["sdk/triggerclient/store"]
572+
"pages": [
573+
"sdk/triggerclient/store"
574+
]
536575
},
537576
{
538577
"group": "Instance methods",
@@ -595,7 +634,10 @@
595634
"sdk/dynamictrigger/constructor",
596635
{
597636
"group": "Instance methods",
598-
"pages": ["sdk/dynamictrigger/register", "sdk/dynamictrigger/unregister"]
637+
"pages": [
638+
"sdk/dynamictrigger/register",
639+
"sdk/dynamictrigger/unregister"
640+
]
599641
}
600642
]
601643
},
@@ -606,7 +648,10 @@
606648
"sdk/dynamicschedule/constructor",
607649
{
608650
"group": "Instance methods",
609-
"pages": ["sdk/dynamicschedule/register", "sdk/dynamicschedule/unregister"]
651+
"pages": [
652+
"sdk/dynamicschedule/register",
653+
"sdk/dynamicschedule/unregister"
654+
]
610655
}
611656
]
612657
},
@@ -618,7 +663,9 @@
618663
},
619664
{
620665
"group": "HTTP Reference",
621-
"pages": ["sdk/api-reference/events/create-an-event"]
666+
"pages": [
667+
"sdk/api-reference/events/create-an-event"
668+
]
622669
},
623670
{
624671
"group": "React SDK",
@@ -633,12 +680,14 @@
633680
{
634681
"group": "Overview",
635682
"version": "v2",
636-
"pages": ["examples/introduction"]
683+
"pages": [
684+
"examples/introduction"
685+
]
637686
}
638687
],
639688
"footerSocials": {
640689
"twitter": "https://twitter.com/triggerdotdev",
641690
"github": "https://github.com/triggerdotdev",
642691
"linkedin": "https://www.linkedin.com/company/triggerdotdev"
643692
}
644-
}
693+
}

0 commit comments

Comments
 (0)