Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: realtime #1402

Merged
merged 46 commits into from
Oct 21, 2024
Merged

feat: realtime #1402

merged 46 commits into from
Oct 21, 2024

Conversation

ericallam
Copy link
Member

@ericallam ericallam commented Oct 11, 2024

Trigger.dev realtime - powered by electric

Realtime gives you the ability to subscribe to the state of your task runs from:

  • Your server, using our existing SDK
  • Your frontend, using our new @trigger.dev/react-hooks package, along with a new "public token" permission system powered by JWTs

Subscribing from your server

You can use our existing SDK to subscribe to changes to a specific run like so:

import { runs } from "@trigger.dev/sdk/v3";

for await (const run of runs.subscribeToRun("run_1234")) {
  console.log(run);
}

Or you can subscribe to all runs that match a certain tag like so:

import { runs } from "@trigger.dev/sdk/v3";

for await (const run of runs.subscribeToRunsWithTag("user:12345")) {
  console.log(run);
}

Realtime requests aren't counted against the normal API rate-limit requests, but there can be limits on the number of "live" concurrent realtime requests instead.

Subscribing from your frontend

Using our @trigger.dev/react-hooks package, you can subscribe to runs and tags in your react frontend:

import { useRealtimeRun, useRealtimeRunsWithTag } from "@trigger.dev/react-hooks";

export const MyComponent = () => {
  const { run } = useRealtimeRun("run_1234");
  const { runs } = useRealtimeRunsWithTag("user:12345");

  // render your component based on the run state
};

Granting permissions to your frontend is done by generating a "public token" from your server, and passing it to the frontend:

"use server";

import type { exampleTask } from "@/trigger/example";
import { tasks, auth } from "@trigger.dev/sdk/v3";
import { randomUUID } from "node:crypto";

// This is a Server Action in Next.js
export async function triggerExampleTask() {
  const handle = await tasks.trigger<typeof exampleTask>("example", {
    id: randomUUID(),
  });

  // When triggering a task, you'll get a publicAccessToken that you can use to subscribe to the triggered run from your frontend
  cookies().set("run_token", handle.publicAccessToken);

  // You can also generate a publicAccessToken and give it scoped permissions
  const publicAccessToken = await auth.createPublicToken({
    scopes: {
      read: {
        runs: ["run_1234"],
        tags: ["user:12345"], // You can also subscribe to tags
      },
    },
    expirationTime: "1h", // The token will expire in 1 hour
  });

  // Redirect to the details page
  redirect(`/runs/${handle.id}`);
}

Then in your frontend, you can use our TriggerAuthContext.Provider component to provide the public token to your components, which will get used by our hooks:

import { TriggerAuthContext } from "@trigger.dev/react-hooks";

export default function ClientRunDetails({
  runId,
  accessToken,
}: {
  runId: string;
  accessToken: string;
}) {
  return (
    <TriggerAuthContext.Provider value={{ accessToken: accessToken }}>
      <RunDetailsWrapper runId={runId} />
    </TriggerAuthContext.Provider>
  );
}

And more!

Run metadata changes

We've made changes to how the run metadata SDK works. Previously, each call to update/save the run metadata made a call to the server to update the value. We've changed this to be much more like logs, where all calls are synchronous and updates are buffered and flushed to the server periodically. This allows you to call metadata.set and metadata.replace (which is what metadata.save has been changed to) as many times as you want without bombarding the server and slowing down your runs.

We've also added the ability to "set" deeply inside an object using JSON paths:

metadata.set("my", { foo: { whatever: 1 } });
metadata.set("$.my.foo.bar", "baz")
metadata.get("my") // { foo: { bar: "baz", whatever: 1 }};

Schema Tasks

We have a new way of defining a task that takes a schema to parse and infer the payload type:

import { schemaTask } from "@trigger.dev/sdk/v3";
import { z } from "zod";

const Task2Payload = z.object({
  bar: z.string(),
});

export const task2 = schemaTask({
  id: "types/task-2",
  schema: Task2Payload,
  run: async (payload, { ctx }) => {
    // payload is now typed as Task2Payload

    return { goodbye: "world" as const };
  },
});

This will work with the following schema libraries:

  • zod
  • yup
  • valibot
  • ark
  • superstruct
  • scale

Increasing tag limits

Run tags can now be up to 128 characters and each run can now have up to 10 tags (instead of 5).

Copy link

changeset-bot bot commented Oct 11, 2024

🦋 Changeset detected

Latest commit: 85e8f47

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 10 packages
Name Type
@trigger.dev/react-hooks Minor
@trigger.dev/sdk Minor
@trigger.dev/core Minor
@trigger.dev/build Minor
trigger.dev Minor
@internal/redis-worker Patch
@internal/zod-worker Patch
@trigger.dev/database Minor
@trigger.dev/otlp-importer Minor
@internal/testcontainers Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@ericallam ericallam marked this pull request as ready for review October 17, 2024 16:05
Copy link

pkg-pr-new bot commented Oct 18, 2024

@trigger.dev/build

pnpm add https://pkg.pr.new/triggerdotdev/trigger.dev/@trigger.dev/build@1402

trigger.dev

pnpm add https://pkg.pr.new/triggerdotdev/trigger.dev@1402

@trigger.dev/core

pnpm add https://pkg.pr.new/triggerdotdev/trigger.dev/@trigger.dev/core@1402

@trigger.dev/sdk

pnpm add https://pkg.pr.new/triggerdotdev/trigger.dev/@trigger.dev/sdk@1402

@trigger.dev/react-hooks

pnpm add https://pkg.pr.new/triggerdotdev/trigger.dev/@trigger.dev/react-hooks@1402

commit: 85e8f47

@ericallam
Copy link
Member Author

ericallam commented Oct 18, 2024

New things that need to be tested:

  • React hooks
  • Server to server realtime usage
  • JWT authentication and access from front-end
  • Realtime concurrency limits
  • Org-override API rate limits
  • schemaTask

Changes that need to be tested

  • runs.list
  • runs.listForProject
  • runs.retrieve (make sure backwards compat)
  • @trigger.dev/platform in the webapp
  • updating tags during a run
  • task and run types
  • ensure SDK compliance with edge runtimes

@ericallam ericallam merged commit 2d8a41b into main Oct 21, 2024
9 checks passed
@ericallam ericallam deleted the feat/realtime branch October 21, 2024 14:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant