chore: import upstream snapshot with attribution
This commit is contained in:
@@ -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 />
|
||||
@@ -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 />
|
||||
@@ -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 />
|
||||
@@ -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 />
|
||||
@@ -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 />
|
||||
@@ -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. You’ll 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>
|
||||
Reference in New Issue
Block a user