Skip to content

Commit 9a5aa58

Browse files
committed
Add task run hierarchical relationships to the database
1 parent 6976311 commit 9a5aa58

File tree

11 files changed

+180
-2
lines changed

11 files changed

+180
-2
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,10 @@ export function RunInspector({
354354
: "–"}
355355
</Property.Value>
356356
</Property.Item>
357+
<Property.Item>
358+
<Property.Label>Run ID</Property.Label>
359+
<Property.Value>{run.id}</Property.Value>
360+
</Property.Item>
357361
</Property.Table>
358362
</div>
359363
) : tab === "context" ? (

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ export class SpanPresenter extends BasePresenter {
229229
};
230230

231231
return {
232+
id: run.id,
232233
friendlyId: run.friendlyId,
233234
status: run.status,
234235
createdAt: run.createdAt,

apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.v3.$projectParam.runs.$runParam.spans.$spanParam/route.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,14 @@ function RunBody({
593593
: "–"}
594594
</Property.Value>
595595
</Property.Item>
596+
<Property.Item>
597+
<Property.Label>Run ID</Property.Label>
598+
<Property.Value>{run.friendlyId}</Property.Value>
599+
</Property.Item>
600+
<Property.Item>
601+
<Property.Label>Internal ID</Property.Label>
602+
<Property.Value>{run.id}</Property.Value>
603+
</Property.Item>
596604
</Property.Table>
597605
</div>
598606
) : tab === "context" ? (

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ export class BatchTriggerTaskService extends BaseService {
113113
options: {
114114
...item.options,
115115
dependentBatch: dependentAttempt?.id ? batch.friendlyId : undefined, // Only set dependentBatch if dependentAttempt is set which means batchTriggerAndWait was called
116+
parentBatch: dependentAttempt?.id ? undefined : batch.friendlyId, // Only set parentBatch if dependentAttempt is NOT set which means batchTrigger was called
116117
},
117118
},
118119
{

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

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ export class TriggerTaskService extends BaseService {
108108
id: true,
109109
status: true,
110110
taskIdentifier: true,
111+
rootTaskRunId: true,
111112
},
112113
},
113114
},
@@ -134,6 +135,22 @@ export class TriggerTaskService extends BaseService {
134135
}
135136
}
136137

138+
const parentAttempt = body.options?.parentAttempt
139+
? await this._prisma.taskRunAttempt.findUnique({
140+
where: { friendlyId: body.options.parentAttempt },
141+
include: {
142+
taskRun: {
143+
select: {
144+
id: true,
145+
status: true,
146+
taskIdentifier: true,
147+
rootTaskRunId: true,
148+
},
149+
},
150+
},
151+
})
152+
: undefined;
153+
137154
const dependentBatchRun = body.options?.dependentBatch
138155
? await this._prisma.batchTaskRun.findUnique({
139156
where: { friendlyId: body.options.dependentBatch },
@@ -145,6 +162,7 @@ export class TriggerTaskService extends BaseService {
145162
id: true,
146163
status: true,
147164
taskIdentifier: true,
165+
rootTaskRunId: true,
148166
},
149167
},
150168
},
@@ -176,6 +194,26 @@ export class TriggerTaskService extends BaseService {
176194
}
177195
}
178196

197+
const parentBatchRun = body.options?.parentBatch
198+
? await this._prisma.batchTaskRun.findUnique({
199+
where: { friendlyId: body.options.parentBatch },
200+
include: {
201+
dependentTaskAttempt: {
202+
include: {
203+
taskRun: {
204+
select: {
205+
id: true,
206+
status: true,
207+
taskIdentifier: true,
208+
rootTaskRunId: true,
209+
},
210+
},
211+
},
212+
},
213+
},
214+
})
215+
: undefined;
216+
179217
return await eventRepository.traceEvent(
180218
taskId,
181219
{
@@ -272,6 +310,24 @@ export class TriggerTaskService extends BaseService {
272310
: {
273311
connect: tagIds.map((id) => ({ id })),
274312
},
313+
parentTaskRunId:
314+
dependentAttempt?.taskRun.id ??
315+
parentAttempt?.taskRun.id ??
316+
dependentBatchRun?.dependentTaskAttempt?.taskRun.id,
317+
parentTaskRunAttemptId:
318+
dependentAttempt?.id ??
319+
parentAttempt?.id ??
320+
dependentBatchRun?.dependentTaskAttempt?.id,
321+
rootTaskRunId:
322+
dependentAttempt?.taskRun.rootTaskRunId ??
323+
dependentAttempt?.taskRun.id ??
324+
parentAttempt?.taskRun.rootTaskRunId ??
325+
parentAttempt?.taskRun.id ??
326+
dependentBatchRun?.dependentTaskAttempt?.taskRun.rootTaskRunId ??
327+
dependentBatchRun?.dependentTaskAttempt?.taskRun.id,
328+
329+
batchId: dependentBatchRun?.id ?? parentBatchRun?.id,
330+
resumeParentOnCompletion: !!(dependentAttempt ?? dependentBatchRun),
275331
},
276332
});
277333

packages/core/src/v3/schemas/api.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,9 @@ export const TriggerTaskRequestBody = z.object({
6868
options: z
6969
.object({
7070
dependentAttempt: z.string().optional(),
71+
parentAttempt: z.string().optional(),
7172
dependentBatch: z.string().optional(),
73+
parentBatch: z.string().optional(),
7274
lockToVersion: z.string().optional(),
7375
queue: QueueOptions.optional(),
7476
concurrencyKey: z.string().optional(),
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
-- AlterTable
2+
ALTER TABLE "TaskRun" ADD COLUMN "batchId" TEXT,
3+
ADD COLUMN "parentTaskRunAttemptId" TEXT,
4+
ADD COLUMN "parentTaskRunId" TEXT,
5+
ADD COLUMN "resumeParentOnCompletion" BOOLEAN NOT NULL DEFAULT false;
6+
7+
-- CreateIndex
8+
CREATE INDEX "TaskRun_parentTaskRunId_idx" ON "TaskRun"("parentTaskRunId");
9+
10+
-- AddForeignKey
11+
ALTER TABLE "TaskRun" ADD CONSTRAINT "TaskRun_parentTaskRunId_fkey" FOREIGN KEY ("parentTaskRunId") REFERENCES "TaskRun"("id") ON DELETE SET NULL ON UPDATE CASCADE;
12+
13+
-- AddForeignKey
14+
ALTER TABLE "TaskRun" ADD CONSTRAINT "TaskRun_parentTaskRunAttemptId_fkey" FOREIGN KEY ("parentTaskRunAttemptId") REFERENCES "TaskRunAttempt"("id") ON DELETE SET NULL ON UPDATE CASCADE;
15+
16+
-- AddForeignKey
17+
ALTER TABLE "TaskRun" ADD CONSTRAINT "TaskRun_batchId_fkey" FOREIGN KEY ("batchId") REFERENCES "BatchTaskRun"("id") ON DELETE SET NULL ON UPDATE CASCADE;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-- AlterTable
2+
ALTER TABLE "TaskRun" ADD COLUMN "rootTaskRunId" TEXT;
3+
4+
-- AddForeignKey
5+
ALTER TABLE "TaskRun" ADD CONSTRAINT "TaskRun_rootTaskRunId_fkey" FOREIGN KEY ("rootTaskRunId") REFERENCES "TaskRun"("id") ON DELETE SET NULL ON UPDATE CASCADE;

packages/database/prisma/schema.prisma

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1720,6 +1720,31 @@ model TaskRun {
17201720
17211721
logsDeletedAt DateTime?
17221722
1723+
/// This represents the original task that that was triggered outside of a Trigger.dev task
1724+
rootTaskRun TaskRun? @relation("TaskRootRun", fields: [rootTaskRunId], references: [id], onDelete: SetNull)
1725+
rootTaskRunId String?
1726+
1727+
/// The root run will have a list of all the descendant runs, children, grand children, etc.
1728+
descendantRuns TaskRun[] @relation("TaskRootRun")
1729+
1730+
/// The immediate parent run of this task run
1731+
parentTaskRun TaskRun? @relation("TaskParentRun", fields: [parentTaskRunId], references: [id], onDelete: SetNull)
1732+
parentTaskRunId String?
1733+
1734+
/// The immediate child runs of this task run
1735+
childRuns TaskRun[] @relation("TaskParentRun")
1736+
1737+
/// The immediate parent attempt of this task run
1738+
parentTaskRunAttempt TaskRunAttempt? @relation("TaskParentRunAttempt", fields: [parentTaskRunAttemptId], references: [id], onDelete: SetNull)
1739+
parentTaskRunAttemptId String?
1740+
1741+
/// The batch run that this task run is a part of
1742+
batch BatchTaskRun? @relation(fields: [batchId], references: [id], onDelete: SetNull)
1743+
batchId String?
1744+
1745+
/// whether or not the task run was created because of a triggerAndWait for batchTriggerAndWait
1746+
resumeParentOnCompletion Boolean @default(false)
1747+
17231748
@@unique([runtimeEnvironmentId, taskIdentifier, idempotencyKey])
17241749
// Task activity graph
17251750
@@index([projectId, createdAt, taskIdentifier])
@@ -1734,6 +1759,8 @@ model TaskRun {
17341759
@@index([spanId])
17351760
// Finding completed runs
17361761
@@index([completedAt])
1762+
// Finding child runs
1763+
@@index([parentTaskRunId])
17371764
}
17381765

17391766
enum TaskRunStatus {
@@ -1881,6 +1908,7 @@ model TaskRunAttempt {
18811908
batchTaskRunItems BatchTaskRunItem[]
18821909
CheckpointRestoreEvent CheckpointRestoreEvent[]
18831910
alerts ProjectAlert[]
1911+
childRuns TaskRun[] @relation("TaskParentRunAttempt")
18841912
18851913
@@unique([taskRunId, number])
18861914
@@index([taskRunId])
@@ -2071,8 +2099,9 @@ model BatchTaskRun {
20712099
items BatchTaskRunItem[]
20722100
runDependencies TaskRunDependency[] @relation("dependentBatchRun")
20732101
2074-
createdAt DateTime @default(now())
2075-
updatedAt DateTime @updatedAt
2102+
createdAt DateTime @default(now())
2103+
updatedAt DateTime @updatedAt
2104+
TaskRun TaskRun[]
20762105
20772106
@@unique([runtimeEnvironmentId, taskIdentifier, idempotencyKey])
20782107
}

packages/trigger-sdk/src/v3/shared.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,7 @@ async function trigger_internal<TPayload, TOutput>(
791791
ttl: options?.ttl,
792792
tags: options?.tags,
793793
maxAttempts: options?.maxAttempts,
794+
parentAttempt: taskContext.ctx?.attempt.id,
794795
},
795796
},
796797
{
@@ -861,6 +862,7 @@ async function batchTrigger_internal<TPayload, TOutput>(
861862
ttl: item.options?.ttl,
862863
tags: item.options?.tags,
863864
maxAttempts: item.options?.maxAttempts,
865+
parentAttempt: taskContext.ctx?.attempt.id,
864866
},
865867
};
866868
})
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { task } from "@trigger.dev/sdk/v3";
2+
3+
export const rootTask = task({
4+
id: "task-hierarchy/root-task",
5+
run: async ({ useWaits = true }: { useWaits: boolean }) => {
6+
console.log("root-task");
7+
8+
if (useWaits) {
9+
await childTask.triggerAndWait({ useWaits });
10+
await childTask.batchTriggerAndWait([{ payload: { useWaits } }]);
11+
} else {
12+
await childTask.trigger({ useWaits });
13+
await childTask.batchTrigger([{ payload: { useWaits } }]);
14+
}
15+
},
16+
});
17+
18+
export const childTask = task({
19+
id: "task-hierarchy/child-task",
20+
run: async ({ useWaits = true }: { useWaits: boolean }) => {
21+
console.log("child-task");
22+
23+
if (useWaits) {
24+
await grandChildTask.triggerAndWait({ useWaits });
25+
await grandChildTask.batchTriggerAndWait([{ payload: { useWaits } }]);
26+
} else {
27+
await grandChildTask.trigger({ useWaits });
28+
await grandChildTask.batchTrigger([{ payload: { useWaits } }]);
29+
}
30+
},
31+
});
32+
33+
export const grandChildTask = task({
34+
id: "task-hierarchy/grand-child-task",
35+
run: async ({ useWaits = true }: { useWaits: boolean }) => {
36+
console.log("grand-child-task");
37+
38+
if (useWaits) {
39+
await greatGrandChildTask.triggerAndWait({ useWaits });
40+
await greatGrandChildTask.batchTriggerAndWait([{ payload: { useWaits } }]);
41+
} else {
42+
await greatGrandChildTask.trigger({ useWaits });
43+
await greatGrandChildTask.batchTrigger([{ payload: { useWaits } }]);
44+
}
45+
},
46+
});
47+
48+
export const greatGrandChildTask = task({
49+
id: "task-hierarchy/great-grand-child-task",
50+
run: async ({ useWaits = true }: { useWaits: boolean }) => {
51+
console.log("great-grand-child-task");
52+
},
53+
});

0 commit comments

Comments
 (0)