Skip to content

Commit ba1fdbc

Browse files
committed
docs: onCancel
1 parent 13f750a commit ba1fdbc

File tree

1 file changed

+101
-2
lines changed

1 file changed

+101
-2
lines changed

docs/upgrade-to-v4.mdx

Lines changed: 101 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,105 @@ tasks.onComplete(({ ctx, result }) => {
170170
});
171171
```
172172

173+
### onCancel
174+
175+
You can now define an `onCancel` hook that is called when a run is cancelled. This is useful if you want to clean up any resources that were allocated for the run.
176+
177+
```ts
178+
tasks.onCancel(({ ctx, signal }) => {
179+
console.log("Run cancelled", signal);
180+
});
181+
```
182+
183+
You can use the `onCancel` hook along with the `signal` passed into the run function to interrupt a call to an external service, for example using the [streamText](https://ai-sdk.dev/docs/reference/ai-sdk-core/stream-text) function from the AI SDK:
184+
185+
```ts
186+
import { logger, tasks, schemaTask } from "@trigger.dev/sdk";
187+
import { streamText } from "ai";
188+
import { z } from "zod";
189+
190+
export const interruptibleChat = schemaTask({
191+
id: "interruptible-chat",
192+
description: "Chat with the AI",
193+
schema: z.object({
194+
prompt: z.string().describe("The prompt to chat with the AI"),
195+
}),
196+
run: async ({ prompt }, { signal }) => {
197+
const chunks: TextStreamPart<{}>[] = [];
198+
199+
// 👇 This is a global onCancel hook, but it's inside of the run function
200+
tasks.onCancel(async () => {
201+
// We have access to the chunks here, and can save them to the database
202+
await saveChunksToDatabase(chunks);
203+
});
204+
205+
try {
206+
const result = streamText({
207+
model: getModel(),
208+
prompt,
209+
experimental_telemetry: {
210+
isEnabled: true,
211+
},
212+
tools: {},
213+
abortSignal: signal, // 👈 Pass the signal to the streamText function, which aborts with the run is cancelled
214+
onChunk: ({ chunk }) => {
215+
chunks.push(chunk);
216+
},
217+
});
218+
219+
const textParts = [];
220+
221+
for await (const part of result.textStream) {
222+
textParts.push(part);
223+
}
224+
225+
return textParts.join("");
226+
} catch (error) {
227+
if (error instanceof Error && error.name === "AbortError") {
228+
// streamText will throw an AbortError if the signal is aborted, so we can handle it here
229+
} else {
230+
throw error;
231+
}
232+
}
233+
},
234+
});
235+
```
236+
237+
The `onCancel` hook can optionally wait for the `run` function to finish, and access the output of the run:
238+
239+
```ts
240+
import { logger, task } from "@trigger.dev/sdk";
241+
import { setTimeout } from "node:timers/promises";
242+
243+
export const cancelExampleTask = task({
244+
id: "cancel-example",
245+
// Signal will be aborted when the task is cancelled 👇
246+
run: async (payload: { message: string }, { signal }) => {
247+
try {
248+
// We pass the signal to setTimeout to abort the timeout if the task is cancelled
249+
await setTimeout(10_000, undefined, { signal });
250+
} catch (error) {
251+
// Ignore the abort error
252+
}
253+
254+
// Do some more work here
255+
256+
return {
257+
message: "Hello, world!",
258+
};
259+
},
260+
onCancel: async ({ runPromise }) => {
261+
// You can await the runPromise to get the output of the task
262+
const output = await runPromise;
263+
},
264+
});
265+
```
266+
267+
<Note>
268+
You will have up to 30 seconds to complete the `runPromise` in the `onCancel` hook. After that
269+
point the process will be killed.
270+
</Note>
271+
173272
### Improved middleware and locals
174273

175274
Our task middleware system is now much more useful. Previously it only ran "around" the `run` function, but now we've hoisted it to the top level and it now runs before/after all the other hooks.
@@ -704,7 +803,7 @@ export const myTask = task({
704803
id: "my-task",
705804
onStart: ({ payload, ctx }) => {},
706805
// The run function still uses separate parameters
707-
run: async ( payload, { ctx }) => {},
806+
run: async (payload, { ctx }) => {},
708807
});
709808
```
710809

@@ -760,4 +859,4 @@ const batchHandle = await tasks.batchTrigger([
760859
// Now you need to call runs.list()
761860
const runs = await batchHandle.runs.list();
762861
console.log(runs);
763-
```
862+
```

0 commit comments

Comments
 (0)