用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/trycompai/comp --skill trigger-advanced-tasks命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Run all audit checks (RBAC, hooks, design system, tests) and verify build
Check code for the most common, high-risk security vulnerabilities (broken access control, tenant isolation, injection, secrets, SSRF, auth/session, unsafe file handling, mass assignment) before it ships. Use after editing any API controller, guard, or auth code (apps/api/src/auth/**), a Prisma schema/query, a file-upload/webhook handler, or before committing/pushing security-sensitive changes.
How to reuse ANY integration check's results in a feature via the universal CheckResultsService (apps/api integration-platform). Use whenever a feature needs data produced by an integration check — "show 2FA status on People", "surface AWS S3 findings in X", "reuse a check's results", "per-user/per-resource results from a connected integration", "which integrations feed task T". Read this BEFORE writing your own IntegrationCheckResult / CheckRunRepository query — don't hand-roll it.
基于 SOC 职业分类
正在显示 SKILL.md
| name | trigger-advanced-tasks |
| description | Comprehensive rules to help you write advanced Trigger.dev tasks |
Source Cursor rule: .cursor/rules/trigger.advanced-tasks.mdc.
Original file scope: **/trigger/**/*.ts.
Original Cursor alwaysApply: false.
Advanced patterns and features for writing tasks
import { task, tags } from '@trigger.dev/sdk';
export const processUser = task({
id: 'process-user',
run: async (payload: { userId: string; orgId: string }, { ctx }) => {
// Add tags during execution
await tags.add(`user_${payload.userId}`);
await tags.add(`org_${payload.orgId}`);
return { processed: true };
},
});
// Trigger with tags
await processUser.trigger(
{ userId: '123', orgId: 'abc' },
{ tags: ['priority', 'user_123', 'org_abc'] }, // Max 10 tags per run
);
// Subscribe to tagged runs
for await (const run of runs.subscribeToRunsWithTag('user_123')) {
console.log(`User task ${run.id}: ${run.status}`);
}
Tag Best Practices:
user_123, org_abc, video:456import { task, queue } from '@trigger.dev/sdk';
// Shared queue for related tasks
const emailQueue = queue({
name: 'email-processing',
concurrencyLimit: 5, // Max 5 emails processing simultaneously
});
// Task-level concurrency
export const oneAtATime = task({
id: 'sequential-task',
queue: { concurrencyLimit: 1 }, // Process one at a time
run: async (payload) => {
// Critical section - only one instance runs
},
});
// Per-user concurrency
export const processUserData = task({
id: 'process-user-data',
run: async (payload: { userId: string }) => {
// Override queue with user-specific concurrency
await childTask.trigger(payload, {
queue: {
name: `user-${payload.userId}`,
concurrencyLimit: 2,
},
});
},
});
export const emailTask = task({
id: 'send-email',
: emailQueue,
: (: { : }) => {
},
});
import { task, retry, AbortTaskRunError } from '@trigger.dev/sdk';
export const resilientTask = task({
id: 'resilient-task',
retry: {
maxAttempts: 10,
factor: 1.8, // Exponential backoff multiplier
minTimeoutInMs: 500,
maxTimeoutInMs: 30_000,
randomize: false,
},
catchError: async ({ error, ctx }) => {
// Custom error handling
if (error.code === 'FATAL_ERROR') {
throw new AbortTaskRunError('Cannot retry this error');
}
// Log error details
console.error(`Task ${ctx.task.id} failed:`, error);
// Allow retry by returning nothing
return { retryAt: new Date(Date.now() + 60000) }; // Retry in 1 minute
},
run: async (payload) => {
// Retry specific operations
const result = await retry.(
() => {
(payload);
},
{ : },
);
response = retry.(, {
: {
: ,
: {
response?. === || response?. >= ;
},
},
});
result;
},
});
export const heavyTask = task({
id: 'heavy-computation',
machine: { preset: 'large-2x' }, // 8 vCPU, 16 GB RAM
maxDuration: 1800, // 30 minutes timeout
run: async (payload, { ctx }) => {
// Resource-intensive computation
if (ctx.machine.preset === 'large-2x') {
// Use all available cores
return await parallelProcessing(payload);
}
return await standardProcessing(payload);
},
});
// Override machine when triggering
await heavyTask.trigger(payload, {
machine: { preset: 'medium-1x' }, // Override for this run
});
Machine Presets:
micro: 0.25 vCPU, 0.25 GB RAMsmall-1x: 0.5 vCPU, 0.5 GB RAM (default)small-2x: 1 vCPU, 1 GB RAMmedium-1x: 1 vCPU, 2 GB RAMmedium-2x: 2 vCPU, 4 GB RAMlarge-1x: 4 vCPU, 8 GB RAMlarge-2x: 8 vCPU, 16 GB RAMimport { task, idempotencyKeys } from '@trigger.dev/sdk';
export const paymentTask = task({
id: 'process-payment',
retry: {
maxAttempts: 3,
},
run: async (payload: { orderId: string; amount: number }) => {
// Automatically scoped to this task run, so if the task is retried, the idempotency key will be the same
const idempotencyKey = await idempotencyKeys.create(`payment-${payload.orderId}`);
// Ensure payment is processed only once
await chargeCustomer.trigger(payload, {
idempotencyKey,
idempotencyKeyTTL: '24h', // Key expires in 24 hours
});
},
});
// Payload-based idempotency
import { createHash } from 'node:crypto';
function createPayloadHash(payload: any): string {
const hash = createHash('sha256');
hash.update(JSON.stringify(payload));
return hash.digest();
}
deduplicatedTask = ({
: ,
: (payload) => {
payloadHash = (payload);
idempotencyKey = idempotencyKeys.(payloadHash);
processData.(payload, { idempotencyKey });
},
});
import { task, metadata } from '@trigger.dev/sdk';
export const batchProcessor = task({
id: 'batch-processor',
run: async (payload: { items: any[] }, { ctx }) => {
const totalItems = payload.items.length;
// Initialize progress metadata
metadata
.set('progress', 0)
.set('totalItems', totalItems)
.set('processedItems', 0)
.set('status', 'starting');
const results = [];
for (let i = 0; i < payload.items.length; i++) {
const item = payload.items[i];
// Process item
const result = await processItem(item);
results.push(result);
// Update progress
const progress = ((i + 1) / totalItems) * 100;
metadata
.set('progress', progress)
.increment('processedItems', )
.(, )
.(, item.);
}
metadata.(, );
{ results, : results. };
},
});
childTask = ({
: ,
: (payload, { ctx }) => {
metadata..(, );
metadata..(, );
{ : };
},
});
'use client';
import { useTaskTrigger } from '@trigger.dev/react-hooks';
import type { myTask } from '../trigger/tasks';
function TriggerButton({ accessToken }: { accessToken: string }) {
const { submit, handle, isLoading } = useTaskTrigger<typeof myTask>('my-task', { accessToken });
return (
<button onClick={() => submit({ data: 'from frontend' })} disabled={isLoading}>
Trigger Task
</button>
);
}
// For payloads > 512KB (max 10MB)
export const largeDataTask = task({
id: 'large-data-task',
run: async (payload: { dataUrl: string }) => {
// Trigger.dev automatically handles large payloads
// For > 10MB, use external storage
const response = await fetch(payload.dataUrl);
const largeData = await response.json();
return { processed: largeData.length };
},
});
// Best practice: Use presigned URLs for very large files
await largeDataTask.trigger({
dataUrl: 'https://s3.amazonaws.com/bucket/large-file.json?presigned=true',
});
await myTask.trigger(payload, {
delay: '2h30m', // Delay execution
ttl: '24h', // Expire if not started within 24 hours
priority: 100, // Higher priority (time offset in seconds)
tags: ['urgent', 'user_123'],
metadata: { source: 'api', version: 'v2' },
queue: {
name: 'priority-queue',
concurrencyLimit: 10,
},
idempotencyKey: 'unique-operation-id',
idempotencyKeyTTL: '1h',
machine: { preset: 'large-1x' },
maxAttempts: 5,
});
// Hidden task - not exported, only used internally
const internalProcessor = task({
id: 'internal-processor',
run: async (payload: { data: string }) => {
return { processed: payload.data.toUpperCase() };
},
});
// Public task that uses hidden task
export const publicWorkflow = task({
id: 'public-workflow',
run: async (payload: { input: string }) => {
// Use hidden task internally
const result = await internalProcessor.triggerAndWait({
data: payload.input,
});
if (result.ok) {
return { output: result.output.processed };
}
throw new Error('Internal processing failed');
},
});
import { task, logger } from '@trigger.dev/sdk';
export const tracedTask = task({
id: 'traced-task',
run: async (payload, { ctx }) => {
logger.info('Task started', { userId: payload.userId });
// Custom trace with attributes
const user = await logger.trace(
'fetch-user',
async (span) => {
span.setAttribute('user.id', payload.userId);
span.setAttribute('operation', 'database-fetch');
const userData = await database.findUser(payload.userId);
span.setAttribute('user.found', !!userData);
return userData;
},
{ userId: payload.userId },
);
logger.debug('User fetched', { user: user.id });
try {
const result = await processUser(user);
logger.info('Processing completed', { result });
return result;
} catch (error) {
logger.(, {
: error.,
: payload.,
});
error;
}
},
});
import { logger, task, usage } from '@trigger.dev/sdk';
export const monitoredTask = task({
id: 'monitored-task',
run: async (payload) => {
// Get current run cost
const currentUsage = await usage.getCurrent();
logger.info('Current cost', {
costInCents: currentUsage.costInCents,
durationMs: currentUsage.durationMs,
});
// Measure specific operation
const { result, compute } = await usage.measure(async () => {
return await expensiveOperation(payload);
});
logger.info('Operation cost', {
costInCents: compute.costInCents,
durationMs: compute.durationMs,
});
return result;
},
});
// Cancel runs
await runs.cancel('run_123');
// Replay runs with same payload
await runs.replay('run_123');
// Retrieve run with cost details
const run = await runs.retrieve('run_123');
console.log(`Cost: ${run.costInCents} cents, Duration: ${run.durationMs}ms`);
Design tasks to be stateless, idempotent, and resilient to failures. Use metadata for state tracking and queues for resource management.