Changelog #82
Realtime beta
Subscribe to realtime updates for your tasks, from your backend or frontend
CTO, Trigger.dev
Today we're releasing three new revolutionary features that will change the way you use Trigger.dev forever:
- Realtime API: Subscribe to runs and get live updates on the run status.
- Public access tokens: Share your runs with the world using public access tokens.
- React hooks: Easily integrate Trigger.dev into your React applications.
So, three things: a realtime API, a way to share your runs with the world, and React hooks.
A realtime API, a way to share your runs with the world, and React hooks.
A realtime API, a way to share your runs with the world... are you getting it?
These are not three separate features. This is one feature, and we are calling it Trigger.dev Realtime (okay actually it is three separate features).
What is Trigger.dev Realtime?
Trigger.dev Realtime has been our #1 requested feature since v3 launched. It allows you to subscribe to runs and get live updates on the run status and more, from your backend or frontend. It's a bridge between your background tasks running on Trigger.dev and your frontend applications.
NOTE
We don't currently support sending streaming responses (e.g. from OpenAI) through the Realtime API. This is something that is planned for a future release.
Realtime API
The Realtime API is built on top of Electric SQL, an open-source PostgreSQL syncing engine. The Trigger.dev API wraps Electric SQL and provides a simple API to subscribe to runs and get real-time updates.
After you trigger a task, you can subscribe to the run using the runs.subscribeToRun
function. This function returns an async iterator that you can use to get updates on the run status.
_11import { runs, tasks } from "@trigger.dev/sdk/v3";_11_11// Somewhere in your backend code_11async function myBackend() {_11 const handle = await tasks.trigger("my-task", { some: "data" });_11_11 for await (const run of runs.subscribeToRun(handle.id)) {_11 // This will log the run every time it changes_11 console.log(run);_11 }_11}
Every time the run changes, the async iterator will yield the updated run. You can use this to update your UI, log the run status, or take any other action.
Alternatively, you can subscribe to changes to any run that includes a specific tag (or tags) using the runs.subscribeToRunsWithTag
function.
_10import { runs } from "@trigger.dev/sdk/v3";_10_10// Somewhere in your backend code_10for await (const run of runs.subscribeToRunsWithTag("user:1234")) {_10 // This will log the run every time it changes, for all runs with the tag "user:1234"_10 console.log(run);_10}
You will receive updates whenever a run changes for the following reasons:
- The run moves to a new state or completes.
- Run tags are added or removed.
- Run metadata is updated.
Public access tokens
While you can subscribe to runs from your backend, we've also added a way for you to selectively expose your runs to the your frontend through public access tokens.
When you create a public access token, you can specify which runs it can access. You can then use this token to subscribe to runs from your frontend.
_21import { auth } from "@trigger.dev/sdk/v3";_21// Somewhere in your backend_21const publicToken = await auth.createPublicToken({_21 scopes: {_21 read: {_21 runs: ["run_1234"],_21 },_21 },_21});_21_21// Somewhere in your frontend_21import { auth } from "@trigger.dev/sdk/v3";_21_21auth.configure({_21 accessToken: publicToken,_21});_21_21for await (const run of runs.subscribeToRun("run_1234")) {_21 // This will log the run every time it changes_21 console.log(run);_21}
Public access tokens are just JWTs with the necessary scopes to access the runs you specify. You can use them to subscribe to runs from your frontend, or even share them with others to let them subscribe to your runs. And they don't just work with the Realtime API; you can use them with any Trigger.dev API that supports public access token authentication (which at the moment is just the Realtime API and the runs.retrieve() endpoint).
We'll also auto-generate public access tokens for you when you trigger a task:
_10import { tasks } from "@trigger.dev/sdk/v3";_10import type { myTask } from "./trigger/tasks";_10_10// Somewhere in your backend_10const handle = await tasks.trigger("my-task", { some: "data" });_10_10// This will log the public access token that can be used to subscribe to the run_10console.log(handle.publicAccessToken);
React hooks
Finally, we're releasing a new @trigger.dev/react-hooks
package to make it easy to integrate the Trigger.dev Realtime API into your React applications.
_12import React from "react";_12import { useRealtimeRun } from "@trigger.dev/react-hooks";_12_12function MyComponent() {_12 const { run, error } = useRealtimeRun("run_1234");_12_12 if (error) {_12 return <div>Error: {error.message}</div>;_12 }_12_12 return <div>{JSON.stringify(run)}</div>;_12}
Runs + tags + metadata = flexible real-time updates
We've built the Realtime API on top of existing Trigger.dev features like runs, tags, and run metadata. This means you can use tags to subscribe to multiple runs at once, and you can use run metadata to provide custom realtime updates, outside of the run status and output. As a little demonstration of what is capable with this, we've built a simple Next.js app that combines UploadThing and fal.ai with Trigger.dev Realtime and put together a little walkthrough of how it works:
Get started today
The Realtime API is available in beta now in version 3.1.0
of the Trigger.dev SDK. We're labelling it beta
because we're still working on it, and we'd love to hear your feedback. Checkout our documentation to get started.
If you are self-hosting Trigger.dev, you will need to upgrade to server version 3.1.0
to use the Realtime API and version 0.7.5
of the Electric SQL server to use the Realtime API. See our self-hosting docs for more information.
Other changes
3.1.0 also includes a few other changes & additions:
Sync run metadata
We've updated the Run metadata API to better support Realtime updates by making the metadata API synchronous, and batching metadata updates in the background. This means you will be able to call metadata.set
or metadata.replace
hundreds of times per second without any performance impact. Previously, these calls were asynchronous and would update the run immediately, which could cause performance issues if you were updating metadata frequently.
Schema Tasks
We've added a new task type that we're calling schemaTask
that allows you to define a validation schema for the payload of a task:
_13import { schemaTask } from "@trigger.dev/sdk/v3";_13import { z } from "zod";_13_13const myTask = schemaTask({_13 id: "my-task",_13 schema: z.object({_13 name: z.string(),_13 age: z.number(),_13 }),_13 run: async (payload) => {_13 console.log(payload.name, payload.age);_13 },_13});
We'll infer the type of the payload in the run
function from the schema you provide, and we'll validate the payload before running the task. If the payload doesn't match the schema, we'll throw an error. In addition to a custom schema parser function, we're shipping with support for the following schema libraries:
See our documentation for more information.
What's next?
We're excited to see what you build with Trigger.dev Realtime. We're already working on some improvements, like adding support for streaming responses from services like OpenAI, and we're investigating integrating React Server Components to make it even easier to build real-time applications with Trigger.dev. If you have any feedback or feature requests, please let us know on our feedback board or reach out to us on x or Discord.