Skip to content

Commit 07980f8

Browse files
authored
fix: allow updating run metadata up to 1 hour after completion (#2288)
1 parent 8d5c86f commit 07980f8

File tree

3 files changed

+54
-8
lines changed

3 files changed

+54
-8
lines changed

apps/webapp/app/routes/api.v1.runs.$runId.metadata.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { json } from "@remix-run/server-runtime";
2+
import { tryCatch } from "@trigger.dev/core/utils";
23
import { UpdateMetadataRequestBody } from "@trigger.dev/core/v3";
34
import { z } from "zod";
45
import { updateMetadataService } from "~/services/metadata/updateMetadata.server";
56
import { createActionApiRoute } from "~/services/routeBuilders/apiBuilder.server";
7+
import { ServiceValidationError } from "~/v3/services/baseService.server";
68

79
const ParamsSchema = z.object({
810
runId: z.string(),
@@ -16,7 +18,17 @@ const { action } = createActionApiRoute(
1618
method: "PUT",
1719
},
1820
async ({ authentication, body, params }) => {
19-
const result = await updateMetadataService.call(params.runId, body, authentication.environment);
21+
const [error, result] = await tryCatch(
22+
updateMetadataService.call(params.runId, body, authentication.environment)
23+
);
24+
25+
if (error) {
26+
if (error instanceof ServiceValidationError) {
27+
return json({ error: error.message }, { status: error.status ?? 422 });
28+
}
29+
30+
return json({ error: "Internal Server Error" }, { status: 500 });
31+
}
2032

2133
if (!result) {
2234
return json({ error: "Task Run not found" }, { status: 404 });

apps/webapp/app/services/metadata/updateMetadata.server.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { prisma, PrismaClientOrTransaction } from "~/db.server";
99
import { AuthenticatedEnvironment } from "~/services/apiAuth.server";
1010
import { handleMetadataPacket } from "~/utils/packets";
1111
import { BaseService, ServiceValidationError } from "~/v3/services/baseService.server";
12-
import { isFinalRunStatus } from "~/v3/taskStatus";
1312

1413
import { Effect, Schedule, Duration } from "effect";
1514
import { type RuntimeFiber } from "effect/Fiber";
@@ -18,6 +17,8 @@ import { singleton } from "~/utils/singleton";
1817
import { env } from "~/env.server";
1918
import { setTimeout } from "timers/promises";
2019

20+
const RUN_UPDATABLE_WINDOW_MS = 60 * 60 * 1000; // 1 hour
21+
2122
type BufferedRunMetadataChangeOperation = {
2223
runId: string;
2324
timestamp: number;
@@ -246,6 +247,7 @@ export class UpdateMetadataService extends BaseService {
246247
},
247248
select: {
248249
id: true,
250+
completedAt: true,
249251
status: true,
250252
metadata: true,
251253
metadataType: true,
@@ -269,7 +271,7 @@ export class UpdateMetadataService extends BaseService {
269271
return;
270272
}
271273

272-
if (isFinalRunStatus(taskRun.status)) {
274+
if (!this.#isRunUpdatable(taskRun)) {
273275
throw new ServiceValidationError("Cannot update metadata for a completed run");
274276
}
275277

@@ -391,6 +393,17 @@ export class UpdateMetadataService extends BaseService {
391393
}
392394
}
393395

396+
// Checks to see if a run is updatable
397+
// if there is no completedAt, the run is updatable
398+
// if the run is completed, but the completedAt is within the last 10 minutes, the run is updatable
399+
#isRunUpdatable(run: { completedAt: Date | null }) {
400+
if (!run.completedAt) {
401+
return true;
402+
}
403+
404+
return run.completedAt.getTime() > Date.now() - RUN_UPDATABLE_WINDOW_MS;
405+
}
406+
394407
async #updateRunMetadataDirectly(
395408
runId: string,
396409
body: UpdateMetadataRequestBody,
Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { metadata, task } from "@trigger.dev/sdk";
1+
import { logger, metadata, task } from "@trigger.dev/sdk";
2+
import { setTimeout } from "node:timers/promises";
23

34
export const metadataTestTask = task({
45
id: "metadata-tester",
@@ -8,9 +9,29 @@ export const metadataTestTask = task({
89
maxTimeoutInMs: 1000,
910
factor: 1.5,
1011
},
11-
run: async (payload: any, { ctx }) => {
12-
metadata.set("test-key", "test-value");
13-
metadata.append("test-keys", "test-value");
14-
metadata.increment("test-counter", 1);
12+
run: async (payload: any, { ctx, signal }) => {
13+
let iteration = 0;
14+
15+
while (!signal.aborted) {
16+
await setTimeout(1000);
17+
18+
iteration++;
19+
20+
metadata.set(`test-key-${iteration}`, `test-value-${iteration}`);
21+
metadata.append(`test-keys-${iteration}`, `test-value-${iteration}`);
22+
metadata.increment(`test-counter-${iteration}`, 1);
23+
24+
await setTimeout(1000);
25+
}
26+
27+
logger.info("Run completed", { iteration });
28+
29+
return {
30+
success: true,
31+
};
32+
},
33+
onCancel: async ({ runPromise }) => {
34+
await metadata.flush();
35+
await runPromise;
1536
},
1637
});

0 commit comments

Comments
 (0)