chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:32:57 +08:00
commit cd420f9332
4811 changed files with 884702 additions and 0 deletions
@@ -0,0 +1,159 @@
---
title: "Data processing & ETL workflows"
sidebarTitle: "Data processing & ETL"
description: "Learn how to use Trigger.dev for data processing and ETL (Extract, Transform, Load), including web scraping, database synchronization, batch enrichment and more."
---
import UseCasesCards from "/snippets/use-cases-cards.mdx";
## Overview
Build complex data pipelines that process large datasets without timeouts. Handle streaming analytics, batch enrichment, web scraping, database sync, and file processing with automatic retries and progress tracking.
## Featured examples
<CardGroup cols={3}>
<Card
title="Realtime CSV importer"
icon="book"
href="/guides/example-projects/realtime-csv-importer"
>
Import CSV files with progress streamed live to frontend.
</Card>
<Card title="Web scraper with BrowserBase" icon="book" href="/guides/examples/scrape-hacker-news">
Scrape websites using BrowserBase and Puppeteer.
</Card>
<Card
title="Supabase database webhooks"
icon="book"
href="/guides/frameworks/supabase-edge-functions-database-webhooks"
>
Trigger tasks from Supabase database webhooks.
</Card>
</CardGroup>
## Benefits of using Trigger.dev for data processing & ETL workflows
**Process datasets for hours without timeouts:** Handle multi-hour transformations, large file processing, or complete database exports. No execution time limits.
**Parallel processing with built-in rate limiting:** Process thousands of records simultaneously while respecting API rate limits. Scale efficiently without overwhelming downstream services.
**Stream progress to your users in real-time:** Show row-by-row processing status updating live in your dashboard. Users see exactly where processing is and how long remains.
## Production use cases
<CardGroup cols={1}>
<Card title="MagicSchool AI customer story" href="https://trigger.dev/customers/magicschool-ai-customer-story">
Read how MagicSchool AI uses Trigger.dev to generate insights from millions of student interactions.
</Card>
<Card title="Comp AI customer story" href="https://trigger.dev/customers/comp-ai-customer-story">
Read how Comp AI uses Trigger.dev to automate evidence collection at scale, powering their open source, AI-driven compliance platform.
</Card>
<Card title="Midday customer story" href="https://trigger.dev/customers/midday-customer-story">
Read how Midday use Trigger.dev to sync large volumes of bank transactions in their financial management platform.
</Card>
</CardGroup>
## Example workflow patterns
<Tabs>
<Tab title="CSV file import">
Simple CSV import pipeline. Receives file upload, parses CSV rows, validates data, imports to database with progress tracking.
<div align="center">
```mermaid
graph TB
A[importCSV] --> B[parseCSVFile]
B --> C[validateRows]
C --> D[bulkInsertToDB]
D --> E[notifyCompletion]
```
</div>
</Tab>
<Tab title="Multi-source ETL pipeline">
**Coordinator pattern with parallel extraction**. Batch triggers parallel extraction from multiple sources (APIs, databases, S3), transforms and validates data, loads to data warehouse with monitoring.
<div align="center">
```mermaid
graph TB
A[runETLPipeline] --> B[coordinateExtraction]
B --> C[batchTriggerAndWait]
C --> D[extractFromAPI]
C --> E[extractFromDatabase]
C --> F[extractFromS3]
D --> G[transformData]
E --> G
F --> G
G --> H[validateData]
H --> I[loadToWarehouse]
```
</div>
</Tab>
<Tab title="Parallel web scraping">
**Coordinator pattern with browser automation**. Launches headless browsers in parallel to scrape multiple pages, extracts structured data, cleans and normalizes content, stores in database.
<div align="center">
```mermaid
graph TB
A[scrapeSite] --> B[coordinateScraping]
B --> C[batchTriggerAndWait]
C --> D[scrapePage1]
C --> E[scrapePage2]
C --> F[scrapePageN]
D --> G[cleanData]
E --> G
F --> G
G --> H[normalizeData]
H --> I[storeInDatabase]
```
</div>
</Tab>
<Tab title="Batch data enrichment">
**Coordinator pattern with rate limiting**. Fetches records needing enrichment, batch triggers parallel API calls with configurable concurrency to respect rate limits, validates enriched data, updates database.
<div align="center">
```mermaid
graph TB
A[enrichRecords] --> B[fetchRecordsToEnrich]
B --> C[coordinateEnrichment]
C --> D[batchTriggerAndWait]
D --> E[enrichRecord1]
D --> F[enrichRecord2]
D --> G[enrichRecordN]
E --> H[validateEnrichedData]
F --> H
G --> H
H --> I[updateDatabase]
```
</div>
</Tab>
</Tabs>
<UseCasesCards />
+147
View File
@@ -0,0 +1,147 @@
---
title: "Marketing workflows"
sidebarTitle: "Marketing"
description: "Learn how to use Trigger.dev for marketing workflows, including drip campaigns, behavioral triggers, personalization engines, and AI-powered content workflows"
---
import UseCasesCards from "/snippets/use-cases-cards.mdx";
## Overview
Build marketing workflows from email drip sequences to orchestrating full multi-channel campaigns. Handle multi-day sequences, behavioral triggers, dynamic content generation, and build live analytics dashboards.
## Featured examples
<CardGroup cols={3}>
<Card
title="Email sequences with Resend"
icon="book"
href="/guides/examples/resend-email-sequence"
>
Send multi-day email sequences with wait delays between messages.
</Card>
<Card
title="Product image generator"
icon="book"
href="/guides/example-projects/product-image-generator"
>
Transform product photos into professional marketing images using Replicate.
</Card>
<Card
title="Human-in-the-loop workflow"
icon="book"
href="/guides/example-projects/human-in-the-loop-workflow"
>
Approve marketing content using a human-in-the-loop workflow.
</Card>
</CardGroup>
## Benefits of using Trigger.dev for marketing workflows
**Delays without idle costs:** Wait hours or weeks between steps. Waits over 5 seconds are automatically checkpointed and don't count towards compute usage. Perfect for drip campaigns and scheduled follow-ups.
**Guaranteed delivery:** Messages send exactly once, even after retries. Personalized content isn't regenerated on failure.
**Scale without limits:** Process thousands in parallel while respecting rate limits. Send to entire segments without overwhelming APIs.
## Production use cases
<Card title="Icon customer story" href="https://trigger.dev/customers/icon-customer-story">
Read how Icon uses Trigger.dev to process and generate thousands of videos per month for their AI-driven video creation platform.
</Card>
## Example workflow patterns
<Tabs>
<Tab title="Drip email campaign">
Simple drip campaign. User signs up, waits specified delay, sends personalized email, tracks engagement.
<div align="center">
```mermaid
graph TB
A[userCreateAccount] --> B[sendWelcomeEmail]
B --> C[wait.for 24h]
C --> D[sendProductTipsEmail]
D --> E[wait.for 7d]
E --> F[sendFeedbackEmail]
```
</div>
</Tab>
<Tab title="Multi-channel campaigns">
**Router pattern with delay orchestration**. User action triggers campaign, router selects channel based on preferences (email/SMS/push), coordinates multi-day sequence with delays between messages, tracks engagement across channels.
<div align="center">
```mermaid
graph TB
A[startCampaign] --> B[fetchUserProfile]
B --> C[selectChannel]
C --> D{Preferred<br/>Channel?}
D -->|Email| E[sendEmail1]
D -->|SMS| F[sendSMS1]
D -->|Push| G[sendPush1]
E --> H[wait.for 2d]
F --> H
G --> H
H --> I[sendFollowUp]
I --> J[trackConversion]
```
</div>
</Tab>
<Tab title="AI content with approval">
**Supervisor pattern with approval gate**. Generates AI marketing content (images, copy, assets), pauses with wait.forToken for human review, applies revisions if needed, publishes to channels after approval.
<div align="center">
```mermaid
graph TB
A[createCampaignAssets] --> B[generateAIContent]
B --> C[wait.forToken approval]
C --> D{Approved?}
D -->|Yes| E[publishToChannels]
D -->|Needs revision| F[applyFeedback]
F --> B
```
</div>
</Tab>
<Tab title="Survey response enrichment">
**Coordinator pattern with enrichment**. User completes survey, batch triggers parallel enrichment from CRM/analytics, analyzes and scores responses, updates customer profiles, triggers personalized follow-up campaigns.
<div align="center">
```mermaid
graph TB
A[processSurveyResponse] --> B[coordinateEnrichment]
B --> C[batchTriggerAndWait]
C --> D[fetchCRMData]
C --> E[fetchAnalytics]
C --> F[fetchBehaviorData]
D --> G[analyzeAndScore]
E --> G
F --> G
G --> H[updateCRMProfile]
H --> I[triggerFollowUp]
```
</div>
</Tab>
</Tabs>
<UseCasesCards />
+144
View File
@@ -0,0 +1,144 @@
---
title: "AI media generation workflows"
sidebarTitle: "AI media generation"
description: "Learn how to use Trigger.dev for AI media generation including image creation, video synthesis, audio generation, and multi-modal content workflows"
---
import UseCasesCards from "/snippets/use-cases-cards.mdx";
## Overview
Build AI media generation pipelines that handle unpredictable API latencies and long-running operations. Generate images, videos, audio, and multi-modal content with automatic retries, progress tracking, and no timeout limits.
## Featured examples
<CardGroup cols={3}>
<Card
title="Product image generator"
icon="book"
href="/guides/example-projects/product-image-generator"
>
Transform product photos into professional marketing images using Replicate.
</Card>
<Card
title="Meme generator (human-in-the-loop)"
icon="book"
href="/guides/example-projects/meme-generator-human-in-the-loop"
>
Generate memes with DALL·E 3 and add human approval steps.
</Card>
<Card
title="Vercel AI SDK image generation"
icon="book"
href="/guides/example-projects/vercel-ai-sdk-image-generator"
>
Generate images from text prompts using the Vercel AI SDK.
</Card>
</CardGroup>
## Benefits of using Trigger.dev for AI media generation workflows
**Pay only for active compute, not AI inference time:** Checkpoint-resume pauses during AI API calls. Generate content that takes minutes or hours without paying for idle inference time.
**No timeout limits for long generations:** Handle generations that take minutes or hours without execution limits. Perfect for high-quality video synthesis and complex multi-modal workflows.
**Human approval gates for brand safety:** Add review steps before publishing AI-generated content. Pause workflows for human approval using waitpoint tokens.
## Production use cases
<CardGroup cols={1}>
<Card title="Icon customer story" href="https://trigger.dev/customers/icon-customer-story">
Read how Icon uses Trigger.dev to process and generate thousands of videos per month for their AI-driven video creation platform.
</Card>
<Card title="Papermark customer story" href="https://trigger.dev/customers/papermark-customer-story">
Read how Papermark process thousands of documents per month using Trigger.dev.
</Card>
</CardGroup>
## Example workflow patterns
<Tabs>
<Tab title="AI content with approval">
**Supervisor pattern with approval gate**. Generates AI content, pauses execution with wait.forToken to allow human review, applies feedback if needed, publishes approved content.
<div align="center">
```mermaid
graph TB
A[generateContent] --> B[createWithAI]
B --> C[wait.forToken approval]
C --> D{Approved?}
D -->|Yes| E[publishContent]
D -->|Needs revision| F[applyFeedback]
F --> B
```
</div>
</Tab>
<Tab title="AI image generation">
Simple AI image generation. Receives prompt and parameters, calls OpenAI DALL·E 3, post-processes result, uploads to storage.
<div align="center">
```mermaid
graph TB
A[generateImage] --> B[optimizeImage]
B --> C[uploadToStorage]
C --> D[updateDatabase]
```
</div>
</Tab>
<Tab title="Batch image generation">
**Coordinator pattern with rate limiting**. Receives batch of generation requests, coordinates parallel processing with configurable concurrency to respect API rate limits, validates outputs, stores results.
<div align="center">
```mermaid
graph TB
A[processBatch] --> B[coordinateGeneration]
B --> C[batchTriggerAndWait]
C --> D[generateImage1]
C --> E[generateImage2]
C --> F[generateImageN]
D --> G[validateResults]
E --> G
F --> G
G --> H[storeResults]
H --> I[notifyCompletion]
```
</div>
</Tab>
<Tab title="Multi-step image enhancement">
**Coordinator pattern with sequential processing**. Generates initial content with AI, applies style transfer or enhancement, upscales resolution, optimizes and compresses for delivery.
<div align="center">
```mermaid
graph TB
A[processCreative] --> B[generateWithAI]
B --> C[applyStyleTransfer]
C --> D[upscaleResolution]
D --> E[optimizeAndCompress]
E --> F[uploadToStorage]
```
</div>
</Tab>
</Tabs>
<UseCasesCards />
+191
View File
@@ -0,0 +1,191 @@
---
title: "Media processing workflows"
sidebarTitle: "Media processing"
description: "Learn how to use Trigger.dev for media processing including video transcoding, image optimization, audio transformation, and document conversion."
---
import UseCasesCards from "/snippets/use-cases-cards.mdx";
## Overview
Build media processing pipelines that handle large files and long-running operations. Process videos, images, audio, and documents with automatic retries, progress tracking, and no timeout limits.
## Featured examples
<CardGroup cols={3}>
<Card title="FFmpeg video processing" icon="book" href="/guides/examples/ffmpeg-video-processing">
Process videos and upload results to R2 storage using FFmpeg.
</Card>
<Card
title="Product image generator"
icon="book"
href="/guides/example-projects/product-image-generator"
>
Transform product photos into professional marketing images using Replicate.
</Card>
<Card
title="LibreOffice PDF conversion"
icon="book"
href="/guides/examples/libreoffice-pdf-conversion"
>
Convert documents to PDF using LibreOffice.
</Card>
</CardGroup>
## Benefits of using Trigger.dev for media processing workflows
**Process multi-hour videos without timeouts:** Transcode videos, extract frames, or run CPU-intensive operations for hours. No execution time limits.
**Stream progress to users in real-time:** Show processing status updating live in your UI. Users see exactly where encoding is and how long remains.
**Parallel processing with resource control:** Process hundreds of files simultaneously with configurable concurrency limits. Control resource usage without overwhelming infrastructure.
## Example workflow patterns
<Tabs>
<Tab title="Video transcode">
Simple video transcoding pipeline. Downloads video from storage, batch triggers parallel transcoding to multiple formats and thumbnail extraction, uploads all results.
<div align="center">
```mermaid
graph TB
A[processVideo] --> B[downloadFromStorage]
B --> C[batchTriggerAndWait]
C --> D[transcodeToHD]
C --> E[transcodeToSD]
C --> F[extractThumbnail]
D --> G[uploadToStorage]
E --> G
F --> G
```
</div>
</Tab>
<Tab title="Adaptive video processing">
**Router + Coordinator pattern**. Analyzes video metadata to determine source resolution, routes to appropriate transcoding preset, batch triggers parallel post-processing for thumbnails, preview clips, and chapter detection.
<div align="center">
```mermaid
graph TB
A[processVideoUpload] --> B[analyzeMetadata]
B --> C{Source<br/>Resolution?}
C -->|4K Source| D[transcode4K]
C -->|HD Source| E[transcodeHD]
C -->|SD Source| F[transcodeSD]
D --> G[coordinatePostProcessing]
E --> G
F --> G
G --> H[batchTriggerAndWait]
H --> I[extractThumbnails]
H --> J[generatePreview]
H --> K[detectChapters]
I --> L[uploadToStorage]
J --> L
K --> L
L --> M[notifyComplete]
```
</div>
</Tab>
<Tab title="Smart image optimization">
**Router + Coordinator pattern**. Analyzes image content to detect type, routes to specialized processing (background removal for products, face detection for portraits, scene analysis for landscapes), upscales with AI, batch triggers parallel variant generation.
<div align="center">
```mermaid
graph TB
A[processImageUpload] --> B[analyzeContent]
B --> C{Content<br/>Type?}
C -->|Product| D[removeBackground]
C -->|Portrait| E[detectFaces]
C -->|Landscape| F[analyzeScene]
D --> G[upscaleWithAI]
E --> G
F --> G
G --> H[batchTriggerAndWait]
H --> I[generateWebP]
H --> J[generateThumbnails]
H --> K[generateSocialCrops]
I --> L[uploadToStorage]
J --> L
K --> L
```
</div>
</Tab>
<Tab title="Podcast production">
**Coordinator pattern**. Pre-processes raw audio with noise reduction and speaker diarization, batch triggers parallel tasks for transcription (Deepgram), audio enhancement, and chapter detection, aggregates results to generate show notes and publish.
<div align="center">
```mermaid
graph TB
A[processAudioUpload] --> B[cleanAudio]
B --> C[coordinateProcessing]
C --> D[batchTriggerAndWait]
D --> E[transcribeWithDeepgram]
D --> F[enhanceAudio]
D --> G[detectChapters]
E --> H[generateShowNotes]
F --> H
G --> H
H --> I[publishToPlatforms]
```
</div>
</Tab>
<Tab title="Document extraction with approval">
**Router pattern with human-in-the-loop**. Detects file type and routes to appropriate processor, classifies document with AI to determine type (invoice/contract/receipt), extracts structured data fields, optionally pauses with wait.forToken for human approval.
<div align="center">
```mermaid
graph TB
A[processDocumentUpload] --> B[detectFileType]
B -->|PDF| C[extractText]
B -->|Word/Excel| D[convertToPDF]
B -->|Image| E[runOCR]
C --> F[classifyDocument]
D --> F
E --> F
F -->|Invoice| G[extractLineItems]
F -->|Contract| H[extractClauses]
F -->|Receipt| I[extractExpenses]
G --> J{Needs<br/>Review?}
H --> J
I --> J
J -->|Yes| K[wait.forToken approval]
J -->|No| L[processAndIntegrate]
K --> L
```
</div>
</Tab>
</Tabs>
<UseCasesCards />
+11
View File
@@ -0,0 +1,11 @@
---
title: "Use cases"
sidebarTitle: "Overview"
description: "Explore common use cases for Trigger.dev including data processing, media workflows, marketing automation, and AI generation"
---
import UseCasesCards from "/snippets/use-cases-cards.mdx";
Trigger.dev handles workflows that traditional platforms struggle with: long-running operations, unpredictable API latencies, multi-hour processing, and complex orchestration patterns. Our platform provides no timeout limits, automatic retries, and real-time progress tracking built in.
<UseCasesCards />
+353
View File
@@ -0,0 +1,353 @@
---
title: "Upgrading from v2"
description: "How to upgrade v2 jobs to v3 tasks, and how to use them together."
---
## Changes from v2 to v3
The main difference is that things in v3 are far simpler. That's because in v3 your code is deployed to our servers (unless you self-host) which are long-running.
1. No timeouts.
2. No `io.runTask()` (and no `cacheKeys`).
3. Just use official SDKs, not integrations.
4. `task`s are the new primitive, not `job`s.
## Convert your v2 job using an AI prompt
The prompt in the accordion below gives good results when using Anthropic Claude 3.5 Sonnet. Youll need a relatively large token limit.
<Note>Don't forget to paste your own v2 code in a markdown codeblock at the bottom of the prompt before running it.</Note>
<Accordion title="Copy and paste this prompt in full:">
I would like you to help me convert from Trigger.dev v2 to Trigger.dev v3.
The important differences:
1. The syntax for creating "background jobs" has changed. In v2 it looked like this:
```ts
import { eventTrigger } from "@trigger.dev/sdk";
import { client } from "@/trigger";
import { db } from "@/lib/db";
client.defineJob({
enabled: true,
id: "my-job-id",
name: "My job name",
version: "0.0.1",
// This is triggered by an event using eventTrigger. You can also trigger Jobs with webhooks, on schedules, and more: https://trigger.dev/docs/documentation/concepts/triggers/introduction
trigger: eventTrigger({
name: "theevent.name",
schema: z.object({
phoneNumber: z.string(),
verified: z.boolean(),
}),
}),
run: async (payload, io) => {
//everything needed to be wrapped in io.runTask in v2, to make it possible for long-running code to work
const result = await io.runTask("get-stuff-from-db", async () => {
const socials = await db.query.Socials.findMany({
where: eq(Socials.service, "tiktok"),
});
return socials;
});
io.logger.info("Completed fetch successfully");
},
});
```
In v3 it looks like this:
```ts
import { task } from "@trigger.dev/sdk";
import { db } from "@/lib/db";
export const getCreatorVideosFromTikTok = task({
id: "my-job-id",
run: async (payload: { phoneNumber: string, verified: boolean }) => {
//in v3 there are no timeouts, so you can just use the code as is, no need to wrap in `io.runTask`
const socials = await db.query.Socials.findMany({
where: eq(Socials.service, "tiktok"),
});
//use `logger` instead of `io.logger`
logger.info("Completed fetch successfully");
},
});
```
Notice that the schema on v2 `eventTrigger` defines the payload type. In v3 that needs to be done on the TypeScript type of the `run` payload param.
2. v2 had integrations with some APIs. Any package that isn't `@trigger.dev/sdk` can be replaced with an official SDK. The syntax may need to be adapted.
For example:
v2:
```ts
import { OpenAI } from "@trigger.dev/openai";
const openai = new OpenAI({
id: "openai",
apiKey: process.env.OPENAI_API_KEY!,
});
client.defineJob({
id: "openai-job",
name: "OpenAI Job",
version: "1.0.0",
trigger: invokeTrigger(),
integrations: {
openai, // Add the OpenAI client as an integration
},
run: async (payload, io, ctx) => {
// Now you can access it through the io object
const completion = await io.openai.chat.completions.create("completion", {
model: "gpt-3.5-turbo",
messages: [
{
role: "user",
content: "Create a good programming joke about background jobs",
},
],
});
},
});
```
Would become in v3:
```ts
import OpenAI from "openai";
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
export const openaiJob = task({
id: "openai-job",
run: async (payload) => {
const completion = await openai.chat.completions.create(
{
model: "gpt-3.5-turbo",
messages: [
{
role: "user",
content: "Create a good programming joke about background jobs",
},
],
});
},
});
```
So don't use the `@trigger.dev/openai` package in v3, use the official OpenAI SDK.
Bear in mind that the syntax for the latest official SDK will probably be different from the @trigger.dev integration SDK. You will need to adapt the code accordingly.
3. The most critical difference is that inside the `run` function you do NOT need to wrap everything in `io.runTask`. So anything inside there can be extracted out and be used in the main body of the function without wrapping it.
4. The import for `task` in v3 is `import { task } from "@trigger.dev/sdk";`
5. You can trigger jobs from other jobs. In v2 this was typically done by either calling `io.sendEvent()` or by calling `yourOtherTask.invoke()`. In v3 you call `.trigger()` on the other task, there are no events in v3.
v2:
```ts
export const parentJob = client.defineJob({
id: "parent-job",
run: async (payload, io) => {
//send event
await client.sendEvent({
name: "user.created",
payload: { name: "John Doe", email: "john@doe.com", paidPlan: true },
});
//invoke
await exampleJob.invoke({ foo: "bar" }, {
idempotencyKey: `some_string_here_${
payload.someValue
}_${new Date().toDateString()}`,
});
},
});
```
v3:
```ts
export const parentJob = task({
id: "parent-job",
run: async (payload) => {
//trigger
await userCreated.trigger({ name: "John Doe", email: "john@doe.com", paidPlan: true });
//trigger, you can pass in an idempotency key
await exampleJob.trigger({ foo: "bar" }, {
idempotencyKey: `some_string_here_${
payload.someValue
}_${new Date().toDateString()}`,
});
}
});
```
Can you help me convert the following code from v2 to v3? Please include the full converted code in the answer, do not truncate it anywhere.
</Accordion>
## OpenAI example comparison
This is a (very contrived) example that does a long OpenAI API call (>10s), stores the result in a database, waits for 5 mins, and then returns the result.
### v2
First, the old v2 code, which uses the OpenAI integration. Comments inline:
```ts v2 OpenAI task
import { client } from "~/trigger";
import { eventTrigger } from "@trigger.dev/sdk";
//1. A Trigger.dev integration for OpenAI
import { OpenAI } from "@trigger.dev/openai";
const openai = new OpenAI({
id: "openai",
apiKey: process.env["OPENAI_API_KEY"]!,
});
//2. Use the client to define a "Job"
client.defineJob({
id: "openai-tasks",
name: "OpenAI Tasks",
version: "0.0.1",
trigger: eventTrigger({
name: "openai.tasks",
schema: z.object({
prompt: z.string(),
}),
}),
//3. integrations are added and come through to `io` in the run fn
integrations: {
openai,
},
run: async (payload, io, ctx) => {
//4. You use `io` to get the integration
//5. Also note that "backgroundCreate" was needed for OpenAI
// to do work that lasted longer than your serverless timeout
const chatCompletion = await io.openai.chat.completions.backgroundCreate(
//6. You needed to add "cacheKeys" to any "task"
"background-chat-completion",
{
messages: [{ role: "user", content: payload.prompt }],
model: "gpt-3.5-turbo",
}
);
const result = chatCompletion.choices[0]?.message.content;
if (!result) {
//7. throwing an error at the top-level in v2 failed the task immediately
throw new Error("No result from OpenAI");
}
//8. io.runTask needed to be used to prevent work from happening twice
const dbRow = await io.runTask("store-in-db", async (task) => {
//9. Custom logic can be put here
// Anything returned must be JSON-serializable, so no Date objects etc.
return saveToDb(result);
});
//10. Wait for 5 minutes.
// You need a cacheKey and the 2nd param is a number
await io.wait("wait some time", 60 * 5);
//11. Anything returned must be JSON-serializable, so no Date objects etc.
return result;
},
});
```
### v3
In v3 we eliminate a lot of code mainly because we don't need tricks to try avoid timeouts. Here's the equivalent v3 code:
```ts v3 OpenAI task
import { logger, task, wait } from "@trigger.dev/sdk";
//1. Official OpenAI SDK
import OpenAI from "openai";
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
//2. Jobs don't exist now, use "task"
export const openaiTask = task({
id: "openai-task",
//3. Retries happen if a task throws an error that isn't caught
// The default settings are in your trigger.config.ts (used if not overriden here)
retry: {
maxAttempts: 3,
},
run: async (payload: { prompt: string }) => {
//4. Use the official SDK
//5. No timeouts, so this can take a long time
const chatCompletion = await openai.chat.completions.create({
messages: [{ role: "user", content: payload.prompt }],
model: "gpt-3.5-turbo",
});
const result = chatCompletion.choices[0]?.message.content;
if (!result) {
//6. throwing an error at the top-level will retry the task (if retries are enabled)
throw new Error("No result from OpenAI");
}
//7. No need to use runTask, just call the function
const dbRow = await saveToDb(result);
//8. You can provide seconds, minutes, hours etc.
// You don't need cacheKeys in v3
await wait.for({ minutes: 5 });
//9. You can return anything that's serializable using SuperJSON
// That includes undefined, Date, bigint, RegExp, Set, Map, Error and URL.
return result;
},
});
```
## Triggering tasks comparison
### v2
In v2 there were different trigger types and triggering each type was slightly different.
```ts v2 triggering
async function yourBackendFunction() {
//1. for `eventTrigger` you use `client.sendEvent`
const event = await client.sendEvent({
name: "openai.tasks",
payload: { prompt: "Create a good programming joke about background jobs" },
});
//2. for `invokeTrigger` you'd call `invoke` on the job
const { id } = await invocableJob.invoke({
prompt: "What is the meaning of life?",
});
}
```
### v3
We've unified triggering in v3. You use `trigger()` or `batchTrigger()` which you can do on any type of task. Including scheduled, webhooks, etc if you want.
```ts v3 triggering
async function yourBackendFunction() {
//call `trigger()` on any task
const handle = await openaiTask.trigger({
prompt: "Tell me a programming joke",
});
}
```
## Upgrading your project
1. Make sure to upgrade all of your trigger.dev packages to v3 first.
```bash
npx @trigger.dev/cli@latest update --to 3.0.0
```
2. Follow the [v3 quick start](/quick-start) to get started with v3. Our new CLI will take care of the rest.
## Using v2 together with v3
You can use v2 and v3 in the same codebase. This can be useful where you already have v2 jobs or where we don't support features you need (yet).
<Note>We do not support calling v3 tasks from v2 jobs or vice versa.</Note>