fade22015f
* Adds new features table to top of v4 upgrade guide * Adds wait idempotency to wait-until, wait-for, and wait-for-token pages * Adds new priority docs page and updates the v4 upgrade guide * Adds new task lifecycle hooks * Removes the message about requiring tasks to be exported * Adds new global lifecycle hooks section * Moves sections from upgrade guide into the table * Adds hidden task page * Improves the global lifecycle hooks section * Updates middleware and locals section * Adds new useWaitToken page to the react hooks section * Adds a new ai.tool section * Moves Docker (legacy) page into self-hosting section * Removes known issues from v4 upgrade guide * Replace “toolTask” with “ai.tool” in the Streams page example * Renames guide to “Migrating from v3” and adds redirect * Remove references to v4 * Removes changelog from migration guide * The installation guide now references `@latest update` * Changes all references from `/sdk/v3` to `/sdk` * Updates @v4-beta to @latest * Fixed broken link * Fixes broken link * Adds an upgrade to v4 using AI section * Fixes 2 broken links * Adds an entry for targetting preview branches * Updates the run statuses * Adds boolean helpers section to the runs and realtime pages * Updates the concurrency page * Updates the test page to include the new options * Adds SDK and curl options for the preview branch targeting * Updates new bulk actions page * Remove the releasing concurrency section * Got rid of some more @v4-beta mentions * Improved rate limit docs * Improved migrating docs * Removed commented sections of the docs * useWaitToken hook * Fixed the description * Fix for missing test image --------- Co-authored-by: Matt Aitken <matt@mattaitken.com> Co-authored-by: Dan <8297864+D-K-P@users.noreply.github.com>
306 lines
12 KiB
Plaintext
306 lines
12 KiB
Plaintext
---
|
||
title: "Migrating from v3"
|
||
description: "What's new in v4, how to migrate, and breaking changes."
|
||
---
|
||
|
||
import NodeVersions from "/snippets/node-versions.mdx";
|
||
import MigrateV4UsingAi from "/snippets/migrate-v4-using-ai.mdx";
|
||
|
||
## What's new in v4?
|
||
|
||
| Feature | Description |
|
||
| :------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||
| [Wait for token](/wait-for-token) | Create and wait for tokens to be completed, enabling approval workflows and waiting for arbitrary external conditions. |
|
||
| Wait idempotency | Skip waits if the same idempotency key is used again when using [wait for](/wait-for#wait-idempotency), [wait until](/wait-until#wait-idempotency), or [wait for token](/wait-for-token#wait-idempotency). |
|
||
| [Priority](/runs/priority) | Specify a priority when triggering a task. |
|
||
| [Global lifecycle hooks](/tasks/overview#global-lifecycle-hooks) | Register global lifecycle hooks that are executed for all runs, regardless of the task. |
|
||
| [onWait and onResume](/tasks/overview#onwait-and-onresume-functions) | Run code when a run is paused or resumed because of a wait. |
|
||
| [onComplete](/tasks/overview#oncomplete-function) | Run code when a run completes, regardless of whether it succeeded or failed. |
|
||
| [onCancel](/tasks/overview#oncancel-function) | Run code when a run is cancelled. |
|
||
| [Hidden tasks](/hidden-tasks) | Create tasks that are not exported from your trigger files but can still be executed. |
|
||
| [Middleware & locals](#middleware-and-locals) | The middleware system runs at the top level, executing before and after all lifecycle hooks. The locals API allows sharing data between middleware and hooks. |
|
||
| [useWaitToken](/realtime/react-hooks/use-wait-token) | Use the useWaitToken hook to complete a wait token from a React component. |
|
||
| [ai.tool](/tasks/schemaTask#ai-tool) | Create an AI tool from an existing `schemaTask` to use with the Vercel [AI SDK](https://vercel.com/docs/ai-sdk). |
|
||
|
||
## Node.js support
|
||
|
||
<NodeVersions />
|
||
|
||
## How to migrate to v4
|
||
|
||
First read the deprecations and breaking changes sections below.
|
||
|
||
We recommend the following steps to migrate to v4:
|
||
|
||
1. Install the v4 package.
|
||
2. Run the `trigger dev` CLI command and test your tasks locally, fixing any breaking changes.
|
||
3. Deploy to the staging environment and test your tasks in staging, fixing any breaking changes. (this step is optional, but highly recommended)
|
||
4. Once you've verified that v4 is working as expected, you should deploy your application backend with the updated v4 package.
|
||
5. Once you've deployed your application backend, you should deploy your tasks to the production environment.
|
||
|
||
Note that between steps 4 and 5, runs triggered with the v4 package will continue using v3, and only new runs triggered after step 5 is complete will use v4.
|
||
|
||
<Warning>
|
||
Once v4 is activated in your environment, there will be a period of time where old runs will
|
||
continue to execute using v3, while new runs will use v4. Because these engines use completely
|
||
different underlying queues and concurrency models, it's possible you may have up to double the
|
||
amount of concurrently executing runs. Once the runs drain from the old run engine, the
|
||
concurrency will return to normal.
|
||
</Warning>
|
||
|
||
## Migrate using AI
|
||
|
||
Use the prompt in the accordion below to help you migrate your v3 tasks to v4. The prompt gives good results when using Claude 4 Sonnet. You’ll need a relatively large token limit.
|
||
|
||
<MigrateV4UsingAi />
|
||
|
||
## Installation
|
||
|
||
To opt-in to using v4, you will need to update your dependencies to the latest version:
|
||
|
||
<CodeGroup>
|
||
|
||
```bash npx
|
||
npx trigger.dev@latest update
|
||
```
|
||
|
||
```bash yarn
|
||
yarn dlx trigger.dev@latest update
|
||
```
|
||
|
||
```bash pnpm
|
||
pnpm dlx trigger.dev@latest update
|
||
```
|
||
|
||
</CodeGroup>
|
||
|
||
This command should update all of your `@trigger.dev/*` packages to a `4.x` version.
|
||
|
||
## Deprecations
|
||
|
||
We've deprecated the following APIs:
|
||
|
||
### @trigger.dev/sdk/v3
|
||
|
||
We've deprecated the `@trigger.dev/sdk/v3` import path and moved to a new path:
|
||
|
||
```ts
|
||
// This still works, but will be removed in a future version
|
||
import { task } from "@trigger.dev/sdk/v3";
|
||
|
||
// This is the new path
|
||
import { task } from "@trigger.dev/sdk";
|
||
```
|
||
|
||
### `handleError` and `init`
|
||
|
||
We've renamed the `handleError` hook to `catchError` to better reflect that it can catch and react to errors. `handleError` will be removed in a future version.
|
||
|
||
`init` was previously used to initialize data used in the run function:
|
||
|
||
```ts
|
||
import { task } from "@trigger.dev/sdk";
|
||
|
||
const myTask = task({
|
||
init: async () => {
|
||
return {
|
||
myClient: new MyClient(),
|
||
};
|
||
},
|
||
run: async (payload: any, { ctx, init }) => {
|
||
const client = init.myClient;
|
||
await client.doSomething();
|
||
},
|
||
});
|
||
```
|
||
|
||
This has now been deprecated in favor of the `locals` API and middleware. See the [Improved middleware and locals](/tasks/overview#middleware-and-locals-functions) section for more details.
|
||
|
||
### toolTask
|
||
|
||
We've deprecated the `toolTask` function, which created both a Trigger.dev task and a tool compatible with the Vercel [AI SDK](https://vercel.com/docs/ai-sdk):
|
||
|
||
```ts
|
||
import { toolTask, schemaTask } from "@trigger.dev/sdk";
|
||
import { z } from "zod";
|
||
import { generateText } from "ai";
|
||
|
||
const myToolTask = toolTask({
|
||
id: "my-tool-task",
|
||
run: async (payload: any, { ctx }) => {},
|
||
});
|
||
|
||
export const myAiTask = schemaTask({
|
||
id: "my-ai-task",
|
||
schema: z.object({
|
||
text: z.string(),
|
||
}),
|
||
run: async (payload, { ctx }) => {
|
||
const { text } = await generateText({
|
||
prompt: payload.text,
|
||
model: openai("gpt-4o"),
|
||
tools: {
|
||
myToolTask,
|
||
},
|
||
});
|
||
},
|
||
});
|
||
```
|
||
|
||
We've replaced the `toolTask` function with the `ai.tool` function, which creates an AI tool from an existing `schemaTask`. See the [ai.tool](/tasks/schemaTask#ai-tool) page for more details.
|
||
|
||
## Breaking changes
|
||
|
||
### Queue changes
|
||
|
||
Previously, it was possible to specify a queue name of a queue that did not exist, along with a concurrency limit. The queue would then be created "on-demand" with the specified concurrency limit. If the queue did exist, the concurrency limit of the queue would be updated to the specified value:
|
||
|
||
```ts
|
||
await myTask.trigger({ foo: "bar" }, { queue: { name: "my-queue", concurrencyLimit: 10 } });
|
||
```
|
||
|
||
This is no longer possible, and queues must now be defined ahead of time using the `queue` function:
|
||
|
||
```ts
|
||
import { queue } from "@trigger.dev/sdk";
|
||
|
||
const myQueue = queue({
|
||
name: "my-queue",
|
||
concurrencyLimit: 10,
|
||
});
|
||
```
|
||
|
||
Now when you trigger a task, you can only specify the queue by name:
|
||
|
||
```ts
|
||
await myTask.trigger({ foo: "bar" }, { queue: "my-queue" });
|
||
```
|
||
|
||
Or you can set the queue on the task:
|
||
|
||
```ts
|
||
import { queue, task } from "@trigger.dev/sdk";
|
||
|
||
const myQueue = queue({
|
||
name: "my-queue",
|
||
concurrencyLimit: 10,
|
||
});
|
||
|
||
export const myTask = task({
|
||
id: "my-task",
|
||
queue: myQueue,
|
||
run: async (payload: any, { ctx }) => {},
|
||
});
|
||
|
||
// You can optionally specify the queue directly on the task
|
||
export const myTask2 = task({
|
||
id: "my-task-2",
|
||
queue: {
|
||
name: "my-queue-2",
|
||
concurrencyLimit: 50,
|
||
},
|
||
run: async (payload: any, { ctx }) => {},
|
||
});
|
||
```
|
||
|
||
Now you can trigger these tasks without having to specify the queue name in the trigger options:
|
||
|
||
```ts
|
||
await myTask.trigger({ foo: "bar" }); // Will use the queue defined on the task
|
||
await myTask2.trigger({ foo: "bar" }); // Will use the queue defined on the task
|
||
```
|
||
|
||
### Lifecycle hooks
|
||
|
||
We've changed the function signatures of the lifecycle hooks to be more consistent and easier to use, by unifying all the parameters into a single object that can be destructured.
|
||
|
||
Previously, hooks received a payload as the first argument and then an additional object as the second argument:
|
||
|
||
```ts
|
||
import { task } from "@trigger.dev/sdk";
|
||
|
||
export const myTask = task({
|
||
id: "my-task",
|
||
onStart: (payload, { ctx }) => {},
|
||
run: async (payload, { ctx }) => {},
|
||
});
|
||
```
|
||
|
||
Now, all the parameters are passed in a single object:
|
||
|
||
```ts
|
||
import { task } from "@trigger.dev/sdk";
|
||
|
||
export const myTask = task({
|
||
id: "my-task",
|
||
onStart: ({ payload, ctx }) => {},
|
||
// The run function still uses separate parameters
|
||
run: async (payload, { ctx }) => {},
|
||
});
|
||
```
|
||
|
||
This is true for all the lifecycle hooks:
|
||
|
||
```ts
|
||
import { task } from "@trigger.dev/sdk";
|
||
|
||
export const myTask = task({
|
||
id: "my-task",
|
||
onStart: ({ payload, ctx, task }) => {},
|
||
onSuccess: ({ payload, ctx, task, output }) => {},
|
||
onFailure: ({ payload, ctx, task, error }) => {},
|
||
onWait: ({ payload, ctx, task, wait }) => {},
|
||
onResume: ({ payload, ctx, task, wait }) => {},
|
||
onComplete: ({ payload, ctx, task, result }) => {},
|
||
catchError: ({ payload, ctx, task, error, retry, retryAt, retryDelayInMs }) => {},
|
||
run: async (payload, { ctx }) => {},
|
||
});
|
||
```
|
||
|
||
### Context changes
|
||
|
||
We've made a few small changes to the `ctx` object:
|
||
|
||
- `ctx.attempt.id` and `ctx.attempt.status` have been removed. `ctx.attempt.number` is still available.
|
||
- `ctx.task.exportName` has been removed (since we no longer require tasks to be exported to be triggered).
|
||
|
||
### BatchTrigger changes
|
||
|
||
The `batchTrigger` function no longer returns a `runs` list directly. In v3, you could access the runs directly from the batch handle:
|
||
|
||
```ts
|
||
// In v3
|
||
const batchHandle = await tasks.batchTrigger([
|
||
[myTask, { foo: "bar" }],
|
||
[myOtherTask, { baz: "qux" }],
|
||
]);
|
||
|
||
// You could access runs directly
|
||
console.log(batchHandle.runs);
|
||
```
|
||
|
||
In v4, you now need to use the `runs.list()` method to get the list of runs:
|
||
|
||
```ts
|
||
// In v4
|
||
const batchHandle = await tasks.batchTrigger([
|
||
[myTask, { foo: "bar" }],
|
||
[myOtherTask, { baz: "qux" }],
|
||
]);
|
||
|
||
// Now you need to call runs.list()
|
||
const runs = await batchHandle.runs.list();
|
||
console.log(runs);
|
||
```
|
||
|
||
### OpenTelemetry
|
||
|
||
We are now using newer versions of the OpenTelemetry packages. This means that if you're using custom exporters you may need to update the packages:
|
||
|
||
| Package | Previous Version | New Version | Change Type |
|
||
| ----------------------------------------- | ---------------- | ----------- | ------------ |
|
||
| `@opentelemetry/api-logs` | 0.52.1 | 0.203.0 | Major update |
|
||
| `@opentelemetry/exporter-logs-otlp-http` | 0.52.1 | 0.203.0 | Major update |
|
||
| `@opentelemetry/exporter-trace-otlp-http` | 0.52.1 | 0.203.0 | Major update |
|
||
| `@opentelemetry/instrumentation` | 0.52.1 | 0.203.0 | Major update |
|