Trigger.dev Realtime
Abonnez-vous aux exécutions de tâches et diffusez des données en temps réel depuis le frontend et le backend.
Quand l'utiliser
- Construire des indicateurs de progression pour les tâches longues
- Créer des tableaux de bord en direct montrant l'état des tâches
- Diffuser les réponses IA/LLM vers l'interface utilisateur
- Composants React qui déclenchent et surveillent les tâches
- Attendre l'approbation de l'utilisateur dans les tâches
Authentification
Créer un token d'accès public (Backend)
import { auth } from "@trigger.dev/sdk";
// Token en lecture seule pour des exécutions spécifiques
const publicToken = await auth.createPublicToken({
scopes: {
read: {
runs: ["run_123"],
tasks: ["my-task"],
},
},
expirationTime: "1h",
});
// Passez ce token à votre frontend
Créer un Trigger Token (pour le déclenchement depuis le frontend)
const triggerToken = await auth.createTriggerPublicToken("my-task", {
expirationTime: "30m",
});
Abonnements Backend
import { runs, tasks } from "@trigger.dev/sdk";
// Déclencher et s'abonner
const handle = await tasks.trigger("my-task", { data: "value" });
for await (const run of runs.subscribeToRun(handle.id)) {
console.log(`Status: ${run.status}`);
console.log(`Progress: ${run.metadata?.progress}`);
if (run.status === "COMPLETED") {
console.log("Output:", run.output);
break;
}
}
// S'abonner aux exécutions étiquetées
for await (const run of runs.subscribeToRunsWithTag("user-123")) {
console.log(`Run ${run.id}: ${run.status}`);
}
// S'abonner à un lot
for await (const run of runs.subscribeToBatch(batchId)) {
console.log(`Batch run ${run.id}: ${run.status}`);
}
React Hooks
Installation
npm add @trigger.dev/react-hooks
Déclencher une tâche depuis React
"use client";
import { useRealtimeTaskTrigger } from "@trigger.dev/react-hooks";
import type { myTask } from "../trigger/tasks";
function TaskTrigger({ accessToken }: { accessToken: string }) {
const { submit, run, isLoading } = useRealtimeTaskTrigger<typeof myTask>(
"my-task",
{ accessToken }
);
return (
<div>
<button
onClick={() => submit({ data: "value" })}
disabled={isLoading}
>
Start Task
</button>
{run && (
<div>
<p>Status: {run.status}</p>
<p>Progress: {run.metadata?.progress}%</p>
{run.output && <p>Result: {JSON.stringify(run.output)}</p>}
</div>
)}
</div>
);
}
S'abonner à une exécution existante
"use client";
import { useRealtimeRun } from "@trigger.dev/react-hooks";
import type { myTask } from "../trigger/tasks";
function RunStatus({ runId, accessToken }: { runId: string; accessToken: string }) {
const { run, error } = useRealtimeRun<typeof myTask>(runId, {
accessToken,
onComplete: (run) => {
console.log("Completed:", run.output);
},
});
if (error) return <div>Error: {error.message}</div>;
if (!run) return <div>Loading...</div>;
return (
<div>
<p>Status: {run.status}</p>
<p>Progress: {run.metadata?.progress || 0}%</p>
</div>
);
}
S'abonner aux exécutions étiquetées
"use client";
import { useRealtimeRunsWithTag } from "@trigger.dev/react-hooks";
function UserTasks({ userId, accessToken }: { userId: string; accessToken: string }) {
const { runs } = useRealtimeRunsWithTag(`user-${userId}`, { accessToken });
return (
<ul>
{runs.map((run) => (
<li key={run.id}>{run.id}: {run.status}</li>
))}
</ul>
);
}
Streams en temps réel (IA/LLM)
Définir un Stream (emplacement partagé)
// trigger/streams.ts
import { streams } from "@trigger.dev/sdk";
export const aiStream = streams.define<string>({
id: "ai-output",
});
Canaliser le Stream dans la tâche
import { task } from "@trigger.dev/sdk";
import { aiStream } from "./streams";
export const streamingTask = task({
id: "streaming-task",
run: async (payload: { prompt: string }) => {
const completion = await openai.chat.completions.create({
model: "gpt-4",
messages: [{ role: "user", content: payload.prompt }],
stream: true,
});
const { waitUntilComplete } = aiStream.pipe(completion);
await waitUntilComplete();
},
});
Lire le Stream dans React
"use client";
import { useRealtimeStream } from "@trigger.dev/react-hooks";
import { aiStream } from "../trigger/streams";
function AIResponse({ runId, accessToken }: { runId: string; accessToken: string }) {
const { parts, error } = useRealtimeStream(aiStream, runId, {
accessToken,
throttleInMs: 50,
});
if (error) return <div>Error: {error.message}</div>;
if (!parts) return <div>Waiting for response...</div>;
return <div>{parts.join("")}</div>;
}
Wait Tokens (Humain dans la boucle)
Dans la tâche
import { task, wait } from "@trigger.dev/sdk";
export const approvalTask = task({
id: "approval-task",
run: async (payload) => {
// Traiter les données initiales
const processed = await processData(payload);
// Attendre l'approbation humaine
const approval = await wait.forToken<{ approved: boolean }>({
token: `approval-${payload.id}`,
timeoutInSeconds: 86400, // 24 heures
});
if (approval.approved) {
return await finalizeData(processed);
}
throw new Error("Not approved");
},
});
Compléter le Token depuis React
"use client";
import { useWaitToken } from "@trigger.dev/react-hooks";
function ApprovalButton({ tokenId, accessToken }: { tokenId: string; accessToken: string }) {
const { complete } = useWaitToken(tokenId, { accessToken });
return (
<div>
<button onClick={() => complete({ approved: true })}>
Approve
</button>
<button onClick={() => complete({ approved: false })}>
Reject
</button>
</div>
);
}
Propriétés de l'objet Run
| Propriété | Description |
|---|---|
id |
Identifiant unique de l'exécution |
status |
QUEUED, EXECUTING, COMPLETED, FAILED, CANCELED |
payload |
Entrée de la tâche (typée) |
output |
Résultat de la tâche (typé, une fois complétée) |
metadata |
Données mises à jour en temps réel |
createdAt |
Horodatage de démarrage |
costInCents |
Coût d'exécution |
Bonnes pratiques
- Limiter les tokens — n'accordez que les permissions nécessaires
- Définir des délais d'expiration — n'utilisez pas de tokens de longue durée
- Utiliser des hooks typés — passez les types de tâche pour une inférence correcte
- Gérer les erreurs — vérifiez toujours les erreurs dans les hooks
- Limiter la fréquence des streams — utilisez
throttleInMspour contrôler les re-rendus
Consultez references/realtime.md pour la documentation complète.