Fix return type of runs.retrieve, and allow passing the type of the task to runs.retrieve

This commit is contained in:
Eric Allam
2024-07-23 23:28:14 +01:00
parent 086a0f95c5
commit 979bee50d0
5 changed files with 87 additions and 50 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@trigger.dev/sdk": patch
---
Fix return type of runs.retrieve, and allow passing the type of the task to runs.retrieve
+28 -11
View File
@@ -17,13 +17,17 @@ import {
isRequestOptions, isRequestOptions,
mergeRequestOptions, mergeRequestOptions,
} from "@trigger.dev/core/v3"; } from "@trigger.dev/core/v3";
import { Prettify, RunHandle, apiClientMissingError } from "./shared"; import { AnyTask, Prettify, RunHandle, Task, apiClientMissingError } from "./shared";
import { tracer } from "./tracer"; import { tracer } from "./tracer";
export type RetrieveRunResult<TOutput> = Prettify< export type RetrieveRunResult<TRunId> = Prettify<
TOutput extends RunHandle<infer THandleOutput> TRunId extends RunHandle<infer TOutput>
? Omit<RetrieveRunResponse, "output"> & { output?: THandleOutput } ? Omit<RetrieveRunResponse, "output"> & { output?: TOutput }
: Omit<RetrieveRunResponse, "output"> & { output?: TOutput } : TRunId extends Task<string, any, infer TTaskOutput>
? Omit<RetrieveRunResponse, "output"> & { output?: TTaskOutput }
: TRunId extends string
? RetrieveRunResponse
: never
>; >;
export const runs = { export const runs = {
@@ -139,8 +143,17 @@ function listRunsRequestOptions(
); );
} }
function retrieveRun<TRunId extends RunHandle<any> | string>( // Extract out the expected type of the id, can be either a string or a RunHandle
runId: TRunId, type RunId<TRunId> = TRunId extends RunHandle<any>
? TRunId
: TRunId extends AnyTask
? string
: TRunId extends string
? TRunId
: never;
function retrieveRun<TRunId extends RunHandle<any> | AnyTask | string>(
runId: RunId<TRunId>,
requestOptions?: ApiRequestOptions requestOptions?: ApiRequestOptions
): ApiPromise<RetrieveRunResult<TRunId>> { ): ApiPromise<RetrieveRunResult<TRunId>> {
const apiClient = apiClientManager.client; const apiClient = apiClientManager.client;
@@ -286,15 +299,15 @@ export type PollOptions = { pollIntervalMs?: number };
const MAX_POLL_ATTEMPTS = 500; const MAX_POLL_ATTEMPTS = 500;
async function poll<TRunHandle extends RunHandle<any> | string>( async function poll<TRunId extends RunHandle<any> | AnyTask | string>(
handle: TRunHandle, runId: RunId<TRunId>,
options?: { pollIntervalMs?: number }, options?: { pollIntervalMs?: number },
requestOptions?: ApiRequestOptions requestOptions?: ApiRequestOptions
) { ) {
let attempts = 0; let attempts = 0;
while (attempts++ < MAX_POLL_ATTEMPTS) { while (attempts++ < MAX_POLL_ATTEMPTS) {
const run = await runs.retrieve(handle, requestOptions); const run = await runs.retrieve(runId, requestOptions);
if (run.isCompleted) { if (run.isCompleted) {
return run; return run;
@@ -303,5 +316,9 @@ async function poll<TRunHandle extends RunHandle<any> | string>(
await new Promise((resolve) => setTimeout(resolve, options?.pollIntervalMs ?? 1000)); await new Promise((resolve) => setTimeout(resolve, options?.pollIntervalMs ?? 1000));
} }
throw new Error(`Run ${handle} did not complete after ${MAX_POLL_ATTEMPTS} attempts`); throw new Error(
`Run ${
typeof runId === "string" ? runId : runId.id
} did not complete after ${MAX_POLL_ATTEMPTS} attempts`
);
} }
+2 -2
View File
@@ -337,7 +337,7 @@ export interface Task<TIdentifier extends string, TInput = void, TOutput = any>
batchTriggerAndWait: (items: Array<BatchItem<TInput>>) => Promise<BatchResult<TOutput>>; batchTriggerAndWait: (items: Array<BatchItem<TInput>>) => Promise<BatchResult<TOutput>>;
} }
type AnyTask = Task<string, any, any>; export type AnyTask = Task<string, any, any>;
export type TaskPayload<TTask extends AnyTask> = TTask extends Task<string, infer TInput, any> export type TaskPayload<TTask extends AnyTask> = TTask extends Task<string, infer TInput, any>
? TInput ? TInput
@@ -678,7 +678,7 @@ export async function batchTrigger<TTask extends AnyTask>(
id: TaskIdentifier<TTask>, id: TaskIdentifier<TTask>,
items: Array<BatchItem<TaskPayload<TTask>>>, items: Array<BatchItem<TaskPayload<TTask>>>,
requestOptions?: ApiRequestOptions requestOptions?: ApiRequestOptions
): Promise<BatchRunHandle<TTask>> { ): Promise<BatchRunHandle<TaskOutput<TTask>>> {
return await batchTrigger_internal<TaskPayload<TTask>, TaskOutput<TTask>>( return await batchTrigger_internal<TaskPayload<TTask>, TaskOutput<TTask>>(
"tasks.batchTrigger()", "tasks.batchTrigger()",
id, id,
+2
View File
@@ -21,6 +21,7 @@ import type {
TaskOutput, TaskOutput,
TaskIdentifier, TaskIdentifier,
TaskRunOptions, TaskRunOptions,
AnyTask,
} from "./shared"; } from "./shared";
export type { export type {
@@ -36,6 +37,7 @@ export type {
TaskOutput, TaskOutput,
TaskIdentifier, TaskIdentifier,
TaskRunOptions, TaskRunOptions,
AnyTask,
}; };
/** Creates a task that can be triggered /** Creates a task that can be triggered
+50 -37
View File
@@ -24,58 +24,71 @@ async function main() {
const anyRun = await runs.retrieve(anyHandle); const anyRun = await runs.retrieve(anyHandle);
console.log(`Run ${anyHandle.id} status: ${anyRun.status}, ttl: ${anyRun.ttl}`); console.log(`Run ${anyHandle.id} status: ${anyRun.status}, ttl: ${anyRun.ttl}`, anyRun.output);
const typedRun = await runs.retrieve<typeof createJsonHeroDoc>(anyHandle.id);
console.log(`Run ${anyHandle.id} status: ${typedRun.status}`, typedRun.output);
await new Promise((resolve) => setTimeout(resolve, 121000)); // wait for 2 minutes await new Promise((resolve) => setTimeout(resolve, 121000)); // wait for 2 minutes
const expiredRun = await runs.retrieve(anyRun.id); const expiredRun = await runs.retrieve(anyRun.id);
console.log( console.log(
`Run ${anyHandle.id} status: ${expiredRun.status}, expired at: ${expiredRun.expiredAt}` `Run ${anyHandle.id} status: ${expiredRun.status}, expired at: ${expiredRun.expiredAt}`,
expiredRun.output
); );
// const handle = await tasks.trigger<typeof createJsonHeroDoc>("create-jsonhero-doc", { const handle = await tasks.trigger<typeof createJsonHeroDoc>("create-jsonhero-doc", {
// title: "Hello World", title: "Hello World",
// content: { content: {
// message: "Hello, World!", message: "Hello, World!",
// }, },
// }); });
// console.log(handle); console.log(handle);
// const completedRun = await runs.poll(handle, { pollIntervalMs: 100 }); const typedRetrieveRun = await runs.retrieve(handle);
// console.log(`Run ${handle.id} completed with output:`, completedRun.output); console.log(`Run ${handle.id} status: ${typedRetrieveRun.status}`, typedRetrieveRun.output);
// const run = await tasks.triggerAndPoll<typeof createJsonHeroDoc>("create-jsonhero-doc", { const completedRun = await runs.poll(handle, { pollIntervalMs: 100 });
// title: "Hello World",
// content: {
// message: "Hello, World!",
// },
// });
// console.log(`Run ${run.id} completed with output: `, run.output); console.log(`Run ${handle.id} completed with output:`, completedRun.output);
// const batchHandle = await tasks.batchTrigger<typeof createJsonHeroDoc>("create-jsonhero-doc", [ const run = await tasks.triggerAndPoll<typeof createJsonHeroDoc>("create-jsonhero-doc", {
// { title: "Hello World",
// payload: { content: {
// title: "Hello World", message: "Hello, World!",
// content: { },
// message: "Hello, World!", });
// },
// },
// },
// {
// payload: {
// title: "Hello World 2",
// content: {
// message: "Hello, World 2!",
// },
// },
// },
// ]);
// const run2 = await runs.retrieve(batchHandle.runs[0]); console.log(`Run ${run.id} completed with output: `, run.output);
const batchHandle = await tasks.batchTrigger<typeof createJsonHeroDoc>("create-jsonhero-doc", [
{
payload: {
title: "Hello World",
content: {
message: "Hello, World!",
},
},
},
{
payload: {
title: "Hello World 2",
content: {
message: "Hello, World 2!",
},
},
},
]);
const firstRunHandle = batchHandle.runs[0];
const run2 = await runs.retrieve(firstRunHandle);
console.log(`Run ${run2.id} completed with output: `, run2.output);
} }
main().catch(console.error); main().catch(console.error);