291 lines
8.0 KiB
Plaintext
291 lines
8.0 KiB
Plaintext
---
|
||
title: "Migrating from Defer.run"
|
||
description: "A guide to migrating from Defer to Trigger.dev v3"
|
||
---
|
||
|
||
First of all, you should use the [Trigger.dev v3 Developer Preview](https://trigger.dev/blog/v3-developer-preview-launch/), not version 2. Version 2 is not a good choice if you're coming from Defer as the execution model is very different. [Let us know](https://) if you need v3 access.
|
||
|
||
This guide highlights the differences and should help you migrate your project.
|
||
|
||
## Features coming very soon
|
||
|
||
Here are some features you might be using in Defer that are coming this month to v3:
|
||
|
||
- Triggering a task with a delay (like `assignOptions` delay in Defer) will be available soon – there is [an alternative](#delay) you can use for now.
|
||
|
||
You can view the full feature matrix [here](/v3/feature-matrix).
|
||
|
||
## Differences
|
||
|
||
#### Local development
|
||
|
||
In Defer you run your tasks locally using `npm run dev` (or other package manager). This is simple but it means dev behaved differently from production for your background tasks.
|
||
|
||
With Trigger.dev you need to use our CLI to run a local server that behaves like the deployed production environment. It also means you will see your runs in the dashboard.
|
||
|
||
#### Multiple tasks in a single file
|
||
|
||
In Defer you needed to use a default export in a file inside your `/defer` directory.
|
||
|
||
```ts /defer/longRunningTask.ts
|
||
import { defer } from "@defer/client";
|
||
|
||
async function longRunningTask() {
|
||
// runs a fake task for 30s
|
||
await performLongRunningTask();
|
||
}
|
||
|
||
export default defer(longRunningTask);
|
||
```
|
||
|
||
In Trigger.dev **you use named exports** so you can have multiple tasks in a single file.
|
||
|
||
```ts /trigger/someTasks.ts
|
||
export const longRunningTask = task({
|
||
id: "longRunningTask",
|
||
run: async (payload: any) => {
|
||
//...do stuff
|
||
},
|
||
});
|
||
|
||
export const otherTask = task({
|
||
id: "otherTask",
|
||
run: async (payload: any) => {
|
||
//...do different stuff
|
||
},
|
||
});
|
||
```
|
||
|
||
#### Triggering your tasks
|
||
|
||
In Defer, you wrapped your existing function in `defer()`. Then for simple cases you could just call the function. In other cases, like when you wanted to have a delay you needed to use `assignOptions` to create a new function.
|
||
|
||
```ts /app/actions/actions.ts
|
||
"use server";
|
||
|
||
import longRunningTask from "@/defer/longRunningTask";
|
||
|
||
export async function runLongRunningTask() {
|
||
return await longRunningTask();
|
||
}
|
||
```
|
||
|
||
In Trigger.dev your logic goes in the `run` function of a task. You can then `trigger` and `batchTrigger` that task, with a payload as the first argument.
|
||
|
||
```ts /app/actions/actions.ts
|
||
"use server";
|
||
|
||
import { longRunningTask } from "@/trigger/someTasks";
|
||
|
||
export async function runLongRunningTask() {
|
||
return await longRunningTask.trigger({ foo: "bar" });
|
||
}
|
||
```
|
||
|
||
#### `wait`
|
||
|
||
In Trigger.dev you can use the [wait](/v3/wait) functions to freeze execution of your code until a later date (it can be months later). You won't pay while it's frozen and the state is restored exactly when it wakes (using a technology called CRIU).
|
||
|
||
```ts
|
||
//In Defer you could use "sleep" but that would keep your function running.
|
||
await sleep(1000 * 60 * 5); // 5 minutes but you'd pay for it.
|
||
|
||
//In Trigger.dev you can use wait. We freeze execution if it's more than 30s
|
||
await wait.for({ seconds: 5 });
|
||
await wait.for({ minutes: 10 });
|
||
await wait.for({ hours: 1 });
|
||
await wait.for({ days: 1 });
|
||
await wait.for({ weeks: 1 });
|
||
await wait.for({ months: 1 });
|
||
await wait.for({ years: 1 });
|
||
|
||
//you can wait for a date too
|
||
await wait.until({ date: aFutureDate });
|
||
```
|
||
|
||
#### delay the start of a run
|
||
|
||
In Defer you can do this:
|
||
|
||
```ts
|
||
const delayedRun = assignOptions(someTask, { delay: "10s" });
|
||
await delayedRun();
|
||
```
|
||
|
||
There will be a nice way to do this soon when you call `trigger()` but for now you can use `wait` to get the same behavior:
|
||
|
||
```ts
|
||
export const helloWorld = task({
|
||
id: "hello-world",
|
||
run: async (payload: { delayUntil?: string; delayForSeconds?: number }) => {
|
||
if (payload.delayUntil) {
|
||
await wait.until({ date: new Date(payload.delayUntil) });
|
||
}
|
||
|
||
if (payload.delayForSeconds) {
|
||
await wait.for({ seconds: payload.delayForSeconds });
|
||
}
|
||
|
||
//do stuff
|
||
},
|
||
});
|
||
```
|
||
|
||
## How to migrate
|
||
|
||
### 1. Get Trigger.dev working in your project
|
||
|
||
<Steps>
|
||
|
||
<Step title="Create an organization on Trigger.dev">
|
||
|
||
1. Go to the [Trigger.dev Cloud](https://cloud.trigger.dev)
|
||
2. Create an account
|
||
3. Create an organization with a project (this will be a version 2 project)
|
||
4. [DM us on Discord](https://trigger.dev/discord) or [fill in this form](https://trigger.dev/v3-early-access) and mention Defer in the company name.
|
||
|
||
We will grant you v3 access.
|
||
|
||
</Step>
|
||
|
||
<Step title="Create a v3 project">
|
||
|
||
1. Go to the Projects page
|
||
|
||

|
||
|
||
2. Click "Create a new project"
|
||
|
||

|
||
|
||
3. Make sure you select "Version 3" from the dropdown!
|
||
|
||

|
||
|
||
<Warning>
|
||
If you don't see a dropdown then you don't have v3 access. [Fill in this
|
||
form](https://trigger.dev/v3-early-access) and mention Defer in the company name.
|
||
</Warning>
|
||
|
||
</Step>
|
||
|
||
<Snippet file="v3/step-cli-init.mdx" />
|
||
<Snippet file="v3/step-cli-dev.mdx" />
|
||
<Snippet file="v3/step-run-test.mdx" />
|
||
<Snippet file="v3/step-view-run.mdx" />
|
||
|
||
</Steps>
|
||
|
||
### 2. Migrate your Defer functions to Trigger.dev tasks
|
||
|
||
#### Example 1: Simple function
|
||
|
||
In Defer you might have a function like this.
|
||
|
||
<CodeGroup>
|
||
|
||
```ts /defer/longRunningTask.ts
|
||
import { performLongRunningTask } from "@/utils/performLongRunningTask";
|
||
import { defer } from "@defer/client";
|
||
|
||
async function longRunningTask() {
|
||
// runs a fake task for 30s
|
||
await performLongRunningTask();
|
||
}
|
||
|
||
export default defer(longRunningTask, {
|
||
concurrency: 2, // want maximum 2 executions of this function in parallel
|
||
retry: 5, // adding retry to recover from potential network issues or rate limiting
|
||
});
|
||
```
|
||
|
||
```ts /app/actions/actions.ts
|
||
"use server";
|
||
|
||
import longRunningTask from "@/defer/longRunningTask";
|
||
|
||
export async function runLongRunningTask() {
|
||
return await longRunningTask();
|
||
}
|
||
```
|
||
|
||
</CodeGroup>
|
||
|
||
In Trigger.dev it looks like this:
|
||
|
||
<CodeGroup>
|
||
|
||
```ts /trigger/someTasks.ts
|
||
import { performLongRunningTask } from "@/utils/performLongRunningTask";
|
||
import { task } from "@trigger.dev/sdk/v3";
|
||
|
||
//named export
|
||
export const longRunningTask = task({
|
||
//a unique and stable ID so you can refactor the function name
|
||
id: "long-running-task",
|
||
queue: {
|
||
concurrencyLimit: 2, // want maximum 2 executions of this function in parallel
|
||
},
|
||
retry: {
|
||
maxAttempts: 5, // adding retry to recover from potential network issues or rate limiting
|
||
},
|
||
run: async (payload: any) => {
|
||
// runs a fake task for 30s
|
||
await performLongRunningTask();
|
||
},
|
||
});
|
||
```
|
||
|
||
```ts /app/actions/actions.ts
|
||
"use server";
|
||
|
||
import { longRunningTask } from "@/trigger/longRunningTask";
|
||
|
||
export async function runLongRunningTask() {
|
||
return await longRunningTask.trigger({ foo: "bar" });
|
||
}
|
||
```
|
||
|
||
</CodeGroup>
|
||
|
||
<Warning>
|
||
You need to set your `TRIGGER_SECRET_KEY` environment variable in your `.env` or `.env.local` file
|
||
to trigger tasks from your code. See the [API keys page](/v3/apikeys) for more information.
|
||
</Warning>
|
||
|
||
#### Example 2: A CRON task
|
||
|
||
We call these [scheduled tasks](/v3/tasks-scheduled) in Trigger.dev.
|
||
|
||
In Defer you might have a function like this:
|
||
|
||
```ts
|
||
import { defer } from "@defer/client";
|
||
|
||
async function sendMondayNewletter() {
|
||
// business logic here
|
||
}
|
||
|
||
export default defer.cron(sendMondayNewletter, "0 0 * * 1");
|
||
```
|
||
|
||
In Trigger.dev the task looks like this:
|
||
|
||
```ts
|
||
import { schedules } from "@trigger.dev/sdk/v3";
|
||
|
||
//this task will run when any of the attached schedules trigger
|
||
export const sendMondayNewletter = schedules.task({
|
||
id: "send-monday-newsletter",
|
||
run: async (payload) => {
|
||
// business logic here
|
||
},
|
||
});
|
||
```
|
||
|
||
Then you need to attach a schedule to the task, either using the dashboard or in your code. You can attach unlimited schedules to a task.
|
||
|
||
<Card title="Attaching schedules" icon="clock" href="/v3/tasks-scheduled">
|
||
How to attach a schedule to a task
|
||
</Card>
|