From 341b7282279258ddf37e6e54b62efa2c19334888 Mon Sep 17 00:00:00 2001 From: Nathan Flurry Date: Sat, 22 Nov 2025 18:11:47 -0800 Subject: [PATCH] docs: update docs --- Cargo.lock | 94 +- README.md | 18 +- engine/artifacts/openapi.json | 2 +- .../connect-manual-serverfull-frame.tsx | 6 +- rivetkit-asyncapi/asyncapi.json | 2 +- rivetkit-openapi/openapi.json | 279 ++- .../packages/rivetkit/scripts/dump-openapi.ts | 147 +- .../packages/rivetkit/src/actor/errors.ts | 31 - website/public/llms-full.txt | 2110 ++++++++--------- website/public/llms.txt | 31 +- website/scripts/generateReadme.mjs | 4 +- .../(index)/components/PlatformIcons.tsx | 8 +- .../(index)/sections/TechSection.tsx | 18 +- website/src/content/docs/actors/actions.mdx | 9 +- .../src/content/docs/actors/api-reference.mdx | 8 - .../content/docs/actors/authentication.mdx | 618 ++--- website/src/content/docs/actors/clients.mdx | 736 +++--- .../actors/communicating-between-actors.mdx | 28 +- .../src/content/docs/actors/connections.mdx | 124 +- .../content/docs/actors/design-patterns.mdx | 333 +++ website/src/content/docs/actors/destroy.mdx | 108 + website/src/content/docs/actors/errors.mdx | 4 + website/src/content/docs/actors/events.mdx | 2 +- .../src/content/docs/actors/external-sql.mdx | 4 +- .../actors/fetch-and-websocket-handler.mdx | 584 +---- .../src/content/docs/actors/helper-types.mdx | 2 +- website/src/content/docs/actors/http-api.mdx | 4 + website/src/content/docs/actors/index.mdx | 60 +- website/src/content/docs/actors/lifecycle.mdx | 564 +++-- .../docs/actors/quickstart/backend.mdx | 2 +- .../actors/quickstart/cloudflare-workers.mdx | 58 +- .../docs/actors/quickstart/next-js.mdx | 2 +- .../content/docs/actors/quickstart/react.mdx | 5 +- .../content/docs/actors/request-handler.mdx | 176 ++ website/src/content/docs/actors/scaling.mdx | 46 +- .../docs/actors/sharing-and-joining-state.mdx | 27 +- .../content/docs/actors/websocket-handler.mdx | 217 ++ website/src/content/docs/clients/openapi.mdx | 6 - website/src/content/docs/clients/react.mdx | 9 +- .../docs/connect/cloudflare-workers.mdx | 11 +- website/src/content/docs/connect/hetzner.mdx | 2 +- .../src/content/docs/drivers/file-system.mdx | 1 - website/src/content/docs/drivers/memory.mdx | 1 - .../src/content/docs/general/architecture.mdx | 462 +++- .../docs/general/images/architecture-base.png | Bin 243331 -> 0 bytes .../images/architecture-coordinate.png | Bin 303798 -> 0 bytes .../docs/general/images/rivetkit-dev.png | Bin 0 -> 18340 bytes .../src/content/docs/general/self-hosting.mdx | 4 +- .../docs/general/system-architecture.mdx | 19 - website/src/content/docs/general/webhooks.mdx | 3 - website/src/content/docs/index.mdx | 12 +- .../content/docs/integrations/better-auth.mdx | 406 ---- .../docs/integrations/cloudflare-workers.mdx | 1 - website/src/content/docs/openapi.json | 305 --- website/src/data/deploy/shared.ts | 18 +- website/src/data/integrations/shared.ts | 22 +- website/src/sitemap/mod.ts | 116 +- 57 files changed, 3991 insertions(+), 3878 deletions(-) delete mode 100644 website/src/content/docs/actors/api-reference.mdx create mode 100644 website/src/content/docs/actors/design-patterns.mdx create mode 100644 website/src/content/docs/actors/destroy.mdx create mode 100644 website/src/content/docs/actors/errors.mdx create mode 100644 website/src/content/docs/actors/http-api.mdx create mode 100644 website/src/content/docs/actors/request-handler.mdx create mode 100644 website/src/content/docs/actors/websocket-handler.mdx delete mode 100644 website/src/content/docs/clients/openapi.mdx delete mode 100644 website/src/content/docs/general/images/architecture-base.png delete mode 100644 website/src/content/docs/general/images/architecture-coordinate.png create mode 100644 website/src/content/docs/general/images/rivetkit-dev.png delete mode 100644 website/src/content/docs/general/system-architecture.mdx delete mode 100644 website/src/content/docs/general/webhooks.mdx delete mode 100644 website/src/content/docs/integrations/better-auth.mdx delete mode 100644 website/src/content/docs/openapi.json diff --git a/Cargo.lock b/Cargo.lock index c86cb8d5ee..2a8d514602 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -827,7 +827,7 @@ dependencies = [ [[package]] name = "clickhouse-inserter" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "async-channel", @@ -851,7 +851,7 @@ dependencies = [ [[package]] name = "clickhouse-user-query" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "clickhouse", "serde", @@ -1476,7 +1476,7 @@ checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" [[package]] name = "epoxy" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "axum 0.8.4", @@ -1515,7 +1515,7 @@ dependencies = [ [[package]] name = "epoxy-protocol" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "rivet-util", @@ -1796,7 +1796,7 @@ dependencies = [ [[package]] name = "gasoline" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "async-stream", @@ -1844,7 +1844,7 @@ dependencies = [ [[package]] name = "gasoline-macros" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "proc-macro2", "quote", @@ -2502,7 +2502,7 @@ dependencies = [ [[package]] name = "internal" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "gasoline", @@ -2901,7 +2901,7 @@ dependencies = [ [[package]] name = "namespace" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "epoxy", @@ -3419,7 +3419,7 @@ checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" [[package]] name = "pegboard" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "base64 0.22.1", @@ -3451,7 +3451,7 @@ dependencies = [ [[package]] name = "pegboard-actor-kv" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "futures-util", @@ -3475,7 +3475,7 @@ dependencies = [ [[package]] name = "pegboard-gateway" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "async-trait", @@ -3507,7 +3507,7 @@ dependencies = [ [[package]] name = "pegboard-runner" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "async-trait", @@ -3541,7 +3541,7 @@ dependencies = [ [[package]] name = "pegboard-serverless" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "base64 0.22.1", @@ -4234,7 +4234,7 @@ dependencies = [ [[package]] name = "rivet-api-builder" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "axum 0.8.4", @@ -4277,7 +4277,7 @@ dependencies = [ [[package]] name = "rivet-api-peer" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "axum 0.8.4", @@ -4308,7 +4308,7 @@ dependencies = [ [[package]] name = "rivet-api-public" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "axum 0.8.4", @@ -4341,7 +4341,7 @@ dependencies = [ [[package]] name = "rivet-api-types" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "gasoline", @@ -4356,7 +4356,7 @@ dependencies = [ [[package]] name = "rivet-api-util" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "axum 0.8.4", @@ -4376,7 +4376,7 @@ dependencies = [ [[package]] name = "rivet-bootstrap" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "epoxy", "gasoline", @@ -4392,7 +4392,7 @@ dependencies = [ [[package]] name = "rivet-cache" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "futures-util", @@ -4433,14 +4433,14 @@ dependencies = [ [[package]] name = "rivet-cache-result" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "rivet-util", ] [[package]] name = "rivet-config" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "config", @@ -4458,7 +4458,7 @@ dependencies = [ [[package]] name = "rivet-data" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "gasoline", @@ -4472,7 +4472,7 @@ dependencies = [ [[package]] name = "rivet-dump-openapi" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "rivet-api-public", "serde_json", @@ -4481,7 +4481,7 @@ dependencies = [ [[package]] name = "rivet-engine" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "axum 0.8.4", @@ -4544,7 +4544,7 @@ dependencies = [ [[package]] name = "rivet-env" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "lazy_static", @@ -4554,7 +4554,7 @@ dependencies = [ [[package]] name = "rivet-error" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "indoc", @@ -4566,7 +4566,7 @@ dependencies = [ [[package]] name = "rivet-error-macros" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "indoc", "proc-macro2", @@ -4577,7 +4577,7 @@ dependencies = [ [[package]] name = "rivet-guard" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "axum 0.8.4", @@ -4623,7 +4623,7 @@ dependencies = [ [[package]] name = "rivet-guard-core" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "async-trait", @@ -4669,7 +4669,7 @@ dependencies = [ [[package]] name = "rivet-logs" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "chrono", @@ -4683,7 +4683,7 @@ dependencies = [ [[package]] name = "rivet-metrics" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "console-subscriber", @@ -4701,7 +4701,7 @@ dependencies = [ [[package]] name = "rivet-pools" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "async-nats", @@ -4734,7 +4734,7 @@ dependencies = [ [[package]] name = "rivet-runner-protocol" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "gasoline", @@ -4751,7 +4751,7 @@ dependencies = [ [[package]] name = "rivet-runtime" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "console-subscriber", @@ -4778,7 +4778,7 @@ dependencies = [ [[package]] name = "rivet-service-manager" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "chrono", @@ -4795,7 +4795,7 @@ dependencies = [ [[package]] name = "rivet-telemetry" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "rivet-config", @@ -4819,7 +4819,7 @@ dependencies = [ [[package]] name = "rivet-test-deps" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "futures-util", @@ -4837,7 +4837,7 @@ dependencies = [ [[package]] name = "rivet-test-deps-docker" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "portpicker", @@ -4868,7 +4868,7 @@ dependencies = [ [[package]] name = "rivet-tracing-utils" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "futures-util", "lazy_static", @@ -4878,7 +4878,7 @@ dependencies = [ [[package]] name = "rivet-types" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "gasoline", @@ -4895,7 +4895,7 @@ dependencies = [ [[package]] name = "rivet-ups-protocol" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "base64 0.22.1", @@ -4908,7 +4908,7 @@ dependencies = [ [[package]] name = "rivet-util" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "async-trait", @@ -4940,7 +4940,7 @@ dependencies = [ [[package]] name = "rivet-util-id" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "serde", "thiserror 1.0.69", @@ -4951,7 +4951,7 @@ dependencies = [ [[package]] name = "rivet-workflow-worker" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "epoxy", @@ -6710,7 +6710,7 @@ checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" [[package]] name = "universaldb" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "async-trait", @@ -6738,7 +6738,7 @@ dependencies = [ [[package]] name = "universalpubsub" -version = "2.0.24" +version = "2.0.25-rc.1" dependencies = [ "anyhow", "async-nats", diff --git a/README.md b/README.md index ffe0aef829..b52221bbc5 100644 --- a/README.md +++ b/README.md @@ -119,17 +119,17 @@ Deploy Rivet Actors anywhere - from serverless platforms to your own infrastruct - [Node.js](https://www.rivet.dev/docs/actors/quickstart/backend) - [Bun](https://www.rivet.dev/docs/actors/quickstart/backend) - [Deno](https://github.com/rivet-dev/rivetkit/tree/9a3d850aee45167eadf249fdbae60129bf37e818/examples/deno) -- [Vercel](https://www.rivet.dev/docs/deploy/vercel) *(1-Click Deploy)* +- [Vercel](https://www.rivet.dev/docs/connect/vercel) *(1-Click Deploy)* - [Railway](https://railway.com/deploy/rivet) *(1-Click Deploy)* - [Durable Objects](https://www.rivet.dev/docs/actors/quickstart/backend) -- [Kubernetes](https://www.rivet.dev/docs/deploy/kubernetes) -- [AWS ECS](https://www.rivet.dev/docs/deploy/aws-ecs) -- [Google Cloud Run](https://www.rivet.dev/docs/deploy/gcp-cloud-run) -- [Hetzner](https://www.rivet.dev/docs/deploy/hetzner) -- [VM & Bare Metal](https://www.rivet.dev/docs/deploy/vm-and-bare-metal) -- [AWS Lambda](https://www.rivet.dev/docs/deploy/aws-lambda) *(On The Roadmap)* -- [Supabase](https://www.rivet.dev/docs/deploy/supabase) *(On The Roadmap)* -- [Freestyle](https://www.rivet.dev/docs/deploy/freestyle) *(On The Roadmap)* +- [Kubernetes](https://www.rivet.dev/docs/connect/kubernetes) +- [AWS ECS](https://www.rivet.dev/docs/connect/aws-ecs) +- [Google Cloud Run](https://www.rivet.dev/docs/connect/gcp-cloud-run) +- [Hetzner](https://www.rivet.dev/docs/connect/hetzner) +- [VM & Bare Metal](https://www.rivet.dev/docs/connect/vm-and-bare-metal) +- [AWS Lambda](https://www.rivet.dev/docs/connect/aws-lambda) *(On The Roadmap)* +- [Supabase](https://www.rivet.dev/docs/connect/supabase) *(On The Roadmap)* +- [Freestyle](https://www.rivet.dev/docs/connect/freestyle) *(On The Roadmap)* ## Works With Your Tools diff --git a/engine/artifacts/openapi.json b/engine/artifacts/openapi.json index 396c4b1203..f0ce865757 100644 --- a/engine/artifacts/openapi.json +++ b/engine/artifacts/openapi.json @@ -11,7 +11,7 @@ "name": "Apache-2.0", "identifier": "Apache-2.0" }, - "version": "2.0.24" + "version": "2.0.25-rc.1" }, "paths": { "/actors": { diff --git a/frontend/src/app/dialogs/connect-manual-serverfull-frame.tsx b/frontend/src/app/dialogs/connect-manual-serverfull-frame.tsx index eb0065ab32..df30f0d708 100644 --- a/frontend/src/app/dialogs/connect-manual-serverfull-frame.tsx +++ b/frontend/src/app/dialogs/connect-manual-serverfull-frame.tsx @@ -238,7 +238,7 @@ function Step2({ provider }: { provider: string }) { .with("aws", () => (

(

(

- - // Validate token and return user data - const user = await validateJWT(token); - return ; - }, - - state: , - - actions: = c.conn.auth; - - if (role !== "member") - - const message = ; - - c.state.messages.push(message); - c.broadcast("newMessage", message); - return message; +interface ConnParams + +const chatRoom = actor(, + + onBeforeConnect: async (c, params: ConnParams) => ); } - } + }, + + actions: ); + }, + }, }); ``` -### `onBeforeConnect` Hook +### `createConnState` -Use `onBeforeConnect` when you need access to actor state for authentication: +Use `createConnState` to extract user data from credentials and store it in connection state. This data is accessible in actions via `c.conn.state`. Like `onBeforeConnect`, throwing an error will reject the connection. See [connections](/docs/actors/connections) for more details. ```typescript -const userProfileActor = actor(), - - state: , - - onBeforeConnect: async (c, opts) => = opts; - const userId = await validateUser(params.token); - - // Check if user can access this profile - if (c.state.isPrivate && c.state.ownerId !== userId) +interface ConnParams + +interface ConnState + +const chatRoom = actor(, + + createConnState: async (c, params: ConnParams): Promise => ); + } + return ; }, - - createConnState: (c, opts, params: ) => ; + + actions: = c.conn.state; + + if (role !== "member") ); + } + + c.state.messages.push(); + c.broadcast("newMessage", ); + }, }, - - actions: - - // Update profile... - } - } }); ``` -Prefer `onAuth` over `onBeforeConnect` when possible, as `onAuth` runs on the HTTP server and uses fewer actor resources. +## Available Auth Data + +Authentication hooks have access to several properties: + +| Property | Description | +|----------|-------------| +| `params` | Custom data passed by the client when connecting (see [connection params](/docs/actors/connections#extracting-data-from-connection-params)) | +| `c.request` | The underlying HTTP request object | +| `c.request.headers` | Request headers for tokens, API keys (does not work for `.connect()`) | +| `c.state` | Actor state for authorization decisions (see [state](/docs/actors/state)) | +| `c.key` | The actor's key (see [keys](/docs/actors/keys)) | + +It's recommended to use `params` instead of `c.request.headers` whenever possible since it works for both HTTP & WebSocket connections. + +## Client Usage -## Connection Parameters +### Passing Credentials Pass authentication data when connecting: -```typescript -// Client side -const chat = client.chatRoom.getOrCreate(["general"]); +```typescript } +const client = createClient(); +const chat = client.chatRoom.getOrCreate(["general"], , +}); + +// Authentication will happen on connect by reading connection parameters const connection = chat.connect(); +``` + +```typescript } +const client = createClient(); +const chat = client.chatRoom.getOrCreate(["general"], , +}); -// Or with action calls -const counter = client.counter.getOrCreate(["user-counter"], ); +// Authentication will happen when calling the action by reading input +// parameters +await chat.sendMessage("Hello, world!"); ``` -## Intent-Based Authentication (Experimental) +```typescript } +// This only works for stateless actions, not WebSockets +const client = createClient(, +}); -The `onAuth` hook receives an `intents` parameter indicating what the client wants to do: +const chat = client.chatRoom.getOrCreate(["general"]); -```typescript -const secureActor = actor(, ) => else if (intents.has("connect")) - - throw new UserError("Unknown intent"); - }, - - actions: - } +// Authentication will happen when calling the action by reading headers +await chat.sendMessage("Hello, world!"); +``` + +### Handling Errors + +Authentication errors use the same system as regular errors. See [errors](/docs/actors/errors) for more details. + +```typescript } +const conn = actor.connect(); +conn.onError((error: ActorError) => else if (error.code === "insufficient_permissions") }); ``` -## Error Handling +```typescript } +try catch (error) else if (error instanceof ActorError && error.code === "insufficient_permissions") +} +``` -### Authentication Errors +## Examples + +### JWT -Use specific error types for different authentication failures: +Validate JSON Web Tokens and extract user claims: ```typescript -const protectedActor = actor() => - - try catch (error) - throw new Unauthorized("Invalid authentication token"); +interface ConnParams + +interface ConnState + +const jwtActor = actor(, + + createConnState: (c, params: ConnParams): ConnState => ; + } catch ); } }, - - actions: - return "Admin content"; - } - } + + actions: ); + } + return ; + }, + }, }); ``` -### Client Error Handling +### External Auth Provider -Handle authentication errors on the client: +Validate credentials against an external authentication service: ```typescript -try catch (error) else if (error.code === "FORBIDDEN") -} -``` +interface ConnParams -## Integration with Auth Providers +interface ConnState -### Better Auth Integration +const apiActor = actor(, - Complete integration guide for Better Auth + createConnState: async (c, params: ConnParams): Promise => , + }); -### JWT Authentication + if (!response.ok) ); + } -```typescript -const jwtActor = actor(, ) => - - try ; - } catch (error) + const data = await response.json(); + return ; + }, + + actions: ); + } + return "Premium content"; + }, }, - - actions: = c.conn.auth; - - if (!permissions.includes("write")) - - // Perform action... - return ; - } - } }); ``` -### API Key Authentication +### Using `c.state` In Authorization + +Access actor state via `c.state` and the actor's key via `c.key` to make authorization decisions: ```typescript -const apiActor = actor(, ) => - - // Validate with your API service - const response = await fetch(`$/validate`, - }); - - if (!response.ok) - - const user = await response.json(); - return ; - }, - - actions: - - return "Premium content"; +interface ConnParams + +const userProfile = actor(, + + onBeforeConnect: (c, params: ConnParams) => ); } - } + }, + + actions: ), + }, }); ``` -## Role-Based Access Control +### Role-Based Access Control -Implement RBAC with helper functions: +Create helper functions for common authorization patterns: ```typescript -// auth-helpers.ts -function requireRole(requiredRole: string) ; - - if (roleHierarchy[userRole] ' required`); +const ROLE_HIERARCHY = ; + +interface ConnState + +function requireRole(requiredRole: keyof typeof ROLE_HIERARCHY) }) => ' required`, ); } }; } -// usage in actor -const forumActor = actor() => , - +const forumActor = actor(, + + createConnState: async (c, params: ): Promise => ; + }, + actions: , - - editPost: (c, postId: string, content: string) => - } + + editPost: (c, postId: string, content: string) => , + }, }); ``` -## Testing Authentication +### Rate Limiting -Mock authentication for testing: +Use `c.vars` to track connection attempts and rate limit by user: ```typescript -// test helpers -function createMockAuth(userData: any) ; -} +interface ConnParams -// in tests -describe("Protected Actor", () => ) - }; - - const result = await mockActor.adminOnly(); - expect(result).toBe("Admin content"); - }); - - it("denies non-admin actions", async () => ) - }; - - await expect(mockActor.adminOnly()).rejects.toThrow("Admin access required"); - }); +interface RateLimitEntry + +const rateLimitedActor = actor(, + vars: as Record }, + + onBeforeConnect: async (c, params: ConnParams) => = await validateToken(params.authToken); + + // Check rate limit + const now = Date.now(); + const limit = c.vars.rateLimits[userId]; + + if (limit && limit.resetAt > now && limit.count >= 10) ); + } + + // Update rate limit + if (!limit || limit.resetAt (), + }, }); ``` -## Best Practices +The limits in this example are [ephemeral](/docs/actors/state#ephemeral-variables-vars). If you wish to persist rate limits, you can optionally replace `vars` with `state`. -1. **Use onAuth**: Prefer `onAuth` over `onBeforeConnect` for most authentication -2. **Validate Early**: Authenticate at the HTTP server level when possible -3. **Specific Errors**: Use appropriate error types (Unauthorized, Forbidden) -4. **Rate Limiting**: Consider rate limiting in your authentication logic -5. **Token Refresh**: Handle token expiration gracefully on the client -6. **Audit Logging**: Log authentication events for security monitoring -7. **Least Privilege**: Only grant the minimum permissions needed -## Actor Clients +### Caching Tokens -# Actor Clients +Cache validated tokens in `c.vars` to avoid redundant validation on repeated connections. See [ephemeral variables](/docs/actors/state#ephemeral-variables-vars) for more details. -Learn how to call actions and connect to actors from client applications using Rivet's TypeScript client library. +```typescript +interface ConnParams -Rivet also supports [React](/docs/clients/react) and [Rust](/docs/clients/rust) clients. +interface ConnState -Using the RivetKit client is completely optional. If you prefer to write your own networking logic, you can either: +interface TokenCache ; +} -- Write your own HTTP endpoints and use the client returned from `registry.start` (see below) -- Make HTTP requests directly to the registry (see [OpenAPI spec](/docs/clients/openapi)) +const cachedAuthActor = actor(, + vars: as TokenCache }, -## Client Setup + createConnState: async (c, params: ConnParams): Promise => ; + } -There are several ways to create a client for communicating with actors: + // Validate token (expensive operation) + const payload = await validateToken(token); + if (!payload) ); + } - From your backend server that hosts the registry: + // Cache the result + c.vars.tokenCache[token] = ; - ```typescript } - const = registry.start(); + return ; + }, - const app = new Hono(); + actions: ), + }, +}); +``` +## Clients - app.post("/foo", () => ); +# Clients - serve(app); - ``` +Clients are used to get and communicate with actors from your application. Clients can be created from either your frontend or backend. - This client doesn't [require authentication](/docs/actors/authentication). +## Creating a Client - For frontend applications or external services connecting to your Rivet backend: + For frontend applications or external services: ```typescript } - // IMPORTANT: Must use `type` - - const client = createClient("http://localhost:8080"); + // Must use `type` - const response = await client.otherActor.getOrCreate().foo(); + const client = createClient(); ``` - Configure the client with additional options: + ```tsx } + // Must use `type` - ```typescript } - const client = createClient("http://localhost:8080", ); + const = createRivetKit(); ``` - This client [requires authentication](/docs/actors/authentication). + Clients include the following options: - **Important**: Use `import type` when importing the registry type in order to - avoid accidentally bundling your backend code. + ```typescript + const client = createClient( + }); + ``` - ```typescript } - // ✅ Do this - // 🚫 Not this + From your backend server that hosts the registry: + + ```typescript + const = registry.start(); ``` From within an actor to communicate with other actors: - ```typescript } + ```typescript const myActor = actor( } }); ``` - This client doesn't [require authentication](/docs/actors/authentication). - Read more about [communicating between actors](/docs/actors/communicating-between-actors). -## `ActorClient` - -The `ActorClient` provides methods for finding and creating actors. All methods return an `ActorHandle` that you can use to call actions or establish connections. +## Getting an Actor -### `get(key?, opts?)` - Find Existing Actor +### `getOrCreate` -Returns a handle to an existing actor or `null` if it doesn't exist: - -```typescript -// Get existing actor by key -const handle = client.myActor.get(["actor-id"]); +Returns a handle to an existing actor or creates one if it doesn't exist: -if (handle) else +```typescript } +const counter = client.counter.getOrCreate("my-counter"); +const count = await counter.increment(5); ``` -### `getOrCreate(key?, opts?)` - Find or Create Actor +```tsx } +const counter = useActor(); -Returns a handle to an existing actor or creates a new one if it doesn't exist: +// Call actions through the connection +await counter.connection?.increment(5); +``` -```typescript -// Get or create actor (synchronous) -const counter = client.counter.getOrCreate(["my-counter"]); +Pass initialization data when creating: -// With initialization input -const game = client.game.getOrCreate(["game-123"], +```typescript } +const game = client.game.getOrCreate("game-123", }); - -// Call actions immediately -const count = await counter.increment(5); ``` -`get()` and `getOrCreate()` are synchronous and return immediately. The actor is created lazily when you first call an action. - -### `create(key?, opts?)` - Create New Actor - -Explicitly creates a new actor instance, failing if one already exists: - -```typescript -// Create new actor (async) -const newGame = await client.game.create(["game-456"], +```tsx } +const game = useActor(, }); - -// Actor is guaranteed to be newly created -await newGame.initialize(); ``` -### `getForId(id, opts?)` - Find by Internal ID +### `get` -Connect to an actor using its internal system ID: +Returns a handle to an existing actor or `null` if it doesn't exist: ```typescript -// Connect by internal ID -const actorId = "55425f42-82f8-451f-82c1-6227c83c9372"; -const actor = client.myActor.getForId(actorId); +const handle = client.myActor.get("actor-id"); -await actor.performAction(); +if (handle) ``` -Prefer using keys over internal IDs for actor discovery. IDs are primarily for debugging and advanced use cases. - -## `ActorHandle` - -An `ActorHandle` represents a reference to an actor instance and provides methods for calling actions and establishing connections. You get an `ActorHandle` from the `ActorClient` methods like `get()`, `getOrCreate()`, and `create()`. - -### Calling Actions +### `create` -You can call actions directly on an `ActorHandle`: +Creates a new actor, failing if one already exists with that key: ```typescript -const counter = client.counter.getOrCreate(["my-counter"]); - -// Call actions directly -const count = await counter.increment(5); -const currentValue = await counter.getCount(); -await counter.reset(); +const newGame = await client.game.create("game-456", +}); ``` -Actions called on an `ActorHandle` are stateless - each call is independent and doesn't maintain a persistent connection to the actor. +### `getForId` -### `fetch(input, init?)` - Raw HTTP Requests - -Make direct HTTP requests to the actor's `onFetch` handler: +Connect to an actor using its internal ID: ```typescript -const actor = client.myActor.getOrCreate(["key"]); - -// GET request -const response = await actor.fetch("/api/hello", ); -const data = await response.json(); - -// POST request with body -const postResponse = await actor.fetch("/api/echo", , - body: JSON.stringify() -}); - -// Can also pass a Request object -const request = new Request("/api/data", ); -const requestResponse = await actor.fetch(request); +const actor = client.myActor.getForId("lrysjam017rhxofttna2x5nzjml610"); ``` -See [Fetch & WebSocket Handler](/docs/actors/fetch-and-websocket-handler) documentation for more information. - -For most use cases, actions provide a higher-level API that's easier to work with than raw HTTP handlers. - -### `websocket(path?, protocols?)` - Raw WebSocket Connections +Prefer using keys over internal IDs for simplicity. -Create direct WebSocket connections to the actor's `onWebSocket` handler: +## Calling Actions -```typescript -const actor = client.myActor.getOrCreate(["key"]); +```typescript } +const counter = client.counter.getOrCreate("my-counter"); -// Basic WebSocket connection -const ws = await actor.websocket(); -ws.addEventListener("message", (event) => ); -ws.send("Hello WebSocket!"); +const count = await counter.increment(5); +const value = await counter.getCount(); +await counter.reset(); +``` -// WebSocket with custom path -const streamWs = await actor.websocket("/stream"); +```tsx } +const counter = useActor(); -// WebSocket with protocols -const protocolWs = await actor.websocket("/", ["chat", "v1"]); +// Call actions through the connection +const count = await counter.connection?.increment(5); +const value = await counter.connection?.getCount(); +await counter.connection?.reset(); ``` -See [Fetch & WebSocket Handler](/docs/actors/fetch-and-websocket-handler) documentation for more information. - -For most use cases, actions & events provide a higher-level API that's easier to work with than raw HTTP handlers. +In JavaScript, actions called without `connect()` are stateless. Each call is independent without a persistent connection. In React, `useActor` automatically manages a persistent connection. -### `connect(params?)` - Establish Stateful Connection +## Connecting to an Actor -To open a stateful connection using `ActorConn`, call `.connect()`: +For real-time use cases, establish a persistent connection to the actor: -```typescript -const counter = client.counter.getOrCreate(["live-counter"]); -const connection = counter.connect(); +```typescript } +const counter = client.counter.getOrCreate("live-counter"); +const conn = counter.connect(); // Listen for events -connection.on("countChanged", (newCount: number) => ); +conn.on("countChanged", (newCount: number) => ); // Call actions through the connection -const result = await connection.increment(1); - -// Clean up when done -await connection.dispose(); +await conn.increment(1); ``` -## `ActorConn` - -Real-time connections enable bidirectional communication between clients and actors through persistent connections. Rivet automatically negotiates between WebSocket (preferred for full duplex) and Server-Sent Events (SSE) as a fallback for restrictive environments. - -For more information on connections, see the [connections documentation](/docs/actors/connections). For more information on handling events, see the [events documentation](/docs/actors/events). - -### Calling Actions +```tsx } +const [count, setCount] = useState(0); -You can also call actions through an `ActorConn`, just like with an `ActorHandle`: +const counter = useActor(); -```typescript -const connection = counter.connect(); +// Listen for events +counter.useEvent("countChanged", (newCount: number) => ); // Call actions through the connection -const count = await connection.increment(5); -const currentValue = await connection.getCount(); +await counter.connection?.increment(1); ``` -### Reconnections - -Connections automatically handle network failures with built-in reconnection logic: - -- **Exponential backoff**: Retry delays increase progressively to avoid overwhelming the server -- **Action queuing**: Actions called while disconnected are queued and sent once reconnected -- **Event resubscription**: Event listeners are automatically restored on reconnection +## Subscribing to Events -### `on(eventName, callback)` - Listen for Events +Listen for events from connected actors: -Listen for events from the actor: +```typescript } +const conn = client.chatRoom.getOrCreate("general").connect(); -```typescript -// Listen for chat messages -connection.on("messageReceived", (message) => : $`); +// Listen for events +conn.on("messageReceived", (message) => : $`); }); -// Listen for game state updates -connection.on("gameStateChanged", (gameState) => ); - -// Listen for player events -connection.on("playerJoined", (player) => joined the game`); -}); +// Listen once +conn.once("gameStarted", () => ); ``` -### `once(eventName, callback)` - Listen Once +```tsx } +const [messages, setMessages] = useState([]); -Listen for an event only once: +const chatRoom = useActor(); -```typescript -// Wait for game to start -connection.once("gameStarted", () => ); +// Listen for events (automatically cleaned up on unmount) +chatRoom.useEvent("messageReceived", (message) => ); ``` -### `dispose()` - Clean Up Connection - -Always dispose of connections when finished to free up resources: +## Full-Stack Type Safety -```typescript -const connection = actor.connect(); +Import types from your registry for end-to-end type safety: -try finally +```typescript } +const client = createClient(); -// Or with automatic cleanup in React/frameworks -useEffect(() => ; -}, []); +// IDE autocomplete shows available actors and actions +const counter = client.counter.getOrCreate("my-counter"); +const count = await counter.increment(5); ``` -**Important:** Disposing a connection: -- Closes the underlying WebSocket or SSE connection -- Removes all event listeners -- Cancels any pending reconnection attempts -- Prevents memory leaks in long-running applications - -## Authentication - -### Connection Parameters - -Pass authentication data when connecting to actors: - -```typescript -// With connection parameters -const chat = client.chatRoom.getOrCreate(["general"], -}); - -const connection = chat.connect(); +```tsx } +const = createRivetKit(); -// Or for action calls -const result = await chat.sendMessage("Hello world!"); +// IDE autocomplete shows available actors and actions +const counter = useActor(); +const count = await counter.connection?.increment(5); ``` -### onAuth Hook Validation +Use `import type` to avoid accidentally bundling backend code in your frontend. -Actors can validate authentication using the `onAuth` hook: - -```typescript -const protectedActor = actor( = opts; - - // Extract token from params or headers - const token = params.authToken || req.headers.get("Authorization"); - - if (!token) ); - } - - // Validate and return user data - const user = await validateJWT(token); - - // Check permissions based on what the client is trying to do - if (intents.has("create") && user.role !== "admin") ); - } - - return ; - }, - - actions: = c.conn.auth; - - if (role !== "admin") ); - } - - return `Hello admin $`; - } - } -}); -``` - -Learn more about [authentication patterns](/docs/actors/authentication). - -## Type Safety - -Rivet provides end-to-end type safety between clients and actors: +## Advanced -### Action Type Safety +### Disposing Clients & Connections -TypeScript validates action signatures and return types: +Dispose clients to close all connections: ```typescript -// TypeScript knows the action signatures -const counter = client.counter.getOrCreate(["my-counter"]); - -const count: number = await counter.increment(5); // ✓ Correct -const invalid = await counter.increment("5"); // ✗ Type error - -// IDE autocomplete shows available actions -counter./* */ +await client.dispose(); ``` -### Client Type Safety - -Import types from your registry for full type safety: +Dispose individual connections when finished: ```typescript -// Client is fully typed -const client = createClient("http://localhost:8080"); +const conn = actor.connect(); -// IDE provides autocomplete for all actors -client./* */ +try finally ``` -## Best Practices - -### `ActorHandle` (Stateless) vs `ActorConn` (Stateful) Clients +### Connection Parameters -**Use `ActorHandle` (Stateless) For:** -- Simple request-response operations -- One-off operations -- Server-side integration +Pass custom data to the actor when connecting: -```typescript -// Good for simple operations -const result = await counter.increment(1); -const status = await server.getStatus(); +```typescript } +const chat = client.chatRoom.getOrCreate("general", +}); ``` -**Use `ActorConn` (Stateful) Connections For:** -- Real-time updates needed -- Event-driven interactions -- Long-lived client sessions - -```typescript -// Good for real-time features -const connection = chatRoom.connect(); -connection.on("messageReceived", updateUI); -await connection.sendMessage("Hello!"); +```tsx } +const chat = useActor(, +}); ``` -### Resource Management +### Authentication -Always clean up connections when finished: +Pass authentication tokens when connecting: -```typescript -// Manual cleanup -const connection = actor.connect(); -try finally +```typescript } +const chat = client.chatRoom.getOrCreate("general", +}); +``` + +```tsx } +const chat = useActor(, +}); ``` -### Error Handling +See [authentication](/docs/actors/authentication) for more details. -Handle connection errors using the `.onError()` method: +### Error Handling ```typescript } -const connection = actor.connect(); - -connection.onError((error) => else if (error.code === 'ACTOR_NOT_FOUND') +const conn = actor.connect(); +conn.onError((error: ActorError) => }); ``` -```tsx } -function ConnectionErrorHandler() ); - - useEffect(() => , 5000); - }); +```typescript } +try catch (error) +} +``` - // Clean up error handler when component unmounts - return unsubscribe; - }, [actor.connection]); +```tsx } +const actor = useActor(); - // ...rest of component... -} +const handleAction = async () => catch (error) + } +}; ``` -### Execute Actions in Parallel +See [errors](/docs/actors/errors) for more details. -You can execute batch requests in parallel: +### Actor Resolution -```typescript -// Batch multiple operations through a connection -const connection = actor.connect(); -await Promise.all([ - connection.operation1(), - connection.operation2(), - connection.operation3(), -]); +`get` and `getOrCreate` return immediately without making a network request. The actor is resolved lazily when you call an action or `connect()`. -// Use getOrCreate for actors you expect to exist -const existing = client.counter.getOrCreate(["known-counter"]); +To explicitly resolve an actor and get its ID, use `resolve()`: -// Use create only when you need a fresh instance -const fresh = await client.counter.create(["new-counter"]); +```typescript +const handle = client.counter.getOrCreate("my-counter"); +const actorId = await handle.resolve(); +console.log(actorId); // "lrysjam017rhxofttna2x5nzjml610" ``` - -However, it's recommended to move this logic to run within the actor instead of the client if executing multiple actions is a common pattern. ## Communicating Between Actors # Communicating Between Actors @@ -1097,10 +985,77 @@ function ConnectionErrorHandler() ); // ...rest of component... } ``` +## Destroying Actors + +# Destroying Actors + +Actors can be permanently destroyed. Common use cases include: + +- User account deletion +- Ending a user session +- Closing a room or game +- Cleaning up temporary resources +- GDPR/compliance data removal + +Actors sleep when idle, so destruction is only needed to permanently remove data — not to save compute. + +## Destroying An Actor + +### Destroy via Action + +To destroy an actor, use `c.destroy()` like this: + +```typescript +interface UserInput + +const userActor = actor(), + actions: , + }, +}); +``` + +### Destroy via HTTP + +Send a DELETE request to destroy an actor. This requires an admin token for authentication. + +```typescript +await fetch(`https://api.rivet.dev/actors/$?namespace=$`, `, + }, +}); +``` + +```bash +curl -X DELETE "https://api.rivet.dev/actors/?namespace=" \ + -H "Authorization: Bearer " +``` + + Creating admin tokens is currently not supported on Rivet Cloud. See the [tracking issue](https://github.com/rivet-dev/rivet/issues/3530). + +### Destroy via Dashboard + +To destroy an actor via the dashboard, navigate to the actor and press the red "X" in the top right. + +## Lifecycle Hook + +Once destroyed, the `onDestroy` hook will be called. This can be used to clean up resources related to the actor. For example: + +```typescript +const resend = new Resend(process.env.RESEND_API_KEY); + +interface UserInput + +const userActor = actor(), + onDestroy: async (c) => , your account has been deleted.`, + }); + }, + actions: , + }, +}); +``` -## Offline & Auto-Reconnection +## Accessing Actor After Destroy -See [client documentation](/docs/actors/communicating-between-actors) for details on reconnection behavior. +Once an actor is destroyed, any subsequent requests to it will return an `actor_not_found` error. The actor's state is permanently deleted. ## Ephemeral Variables # Ephemeral Variables @@ -1199,6 +1154,11 @@ const myActor = actor(, ``` Consult the documentation for each driver to learn more about their respective `DriverContext` types. +## Errors + +# Errors + +TODO ## Events # Events @@ -1400,7 +1360,7 @@ const pool = new Pool(); const userActor = actor(), // Insert user into database when actor starts - onStart: async (c, opts) => , + onWake: async (c, opts) => , actions: ; }, @@ -1415,420 +1375,85 @@ const registry = setup(, }); ``` -```typescript } -const client = createClient("http://localhost:8080"); - -// Create user -const alice = await client.userActor.create("alice", -}); - -alice.updateUser("alice2@example.com"); - -const userData = await alice.getUser(); -console.log("User data:", userData); - -// Create another user -const bob = await client.userActor.create("bob", -}); -const bobData = await bob.getUser(); -``` - -### Using Drizzle ORM - -Here's the same user actor pattern using Drizzle ORM for more type-safe database operations: - -```typescript } -interface ActorInput - -// Define your schema -const users = pgTable("users", ); - -// Create a database connection -const pool = new Pool(); - -// Initialize Drizzle with the pool -const db = drizzle(pool); - -// Create the user actor -const userActor = actor(), - - // Insert user into database when actor starts - onStart: async (c, opts) => ); - }, - - actions: ) - .where(eq(users.username, c.state.username)); - - return ; - }, - - // Get user data - getUser: async (c) => ; - } - } -}); - -const registry = setup(, -}); -``` - -```typescript } -const client = createClient("http://localhost:8080"); - -// Create user -const alice = await client.userActor.create("alice", -}); - -alice.updateUser("alice2@example.com"); - -const userData = await alice.getUser(); -console.log("User data:", userData); - -// Create another user -const bob = await client.userActor.create("bob", -}); -const bobData = await bob.getUser(); -``` -## Fetch and WebSocket Handler - -# Fetch and WebSocket Handler - -Actors can handle HTTP requests and WebSocket connections through the `onFetch` and `onWebSocket` handlers. - -For most use cases, [actions](/docs/actors/actions) and [events](/docs/actors/events) provide high-level connection handling that's easier to work with. However, raw handlers are required when implementing custom use cases or integrating external libraries that need direct access to the underlying HTTP `Request`/`Response` objects or WebSocket connections. - -## Defining Handlers - -### `onFetch(c, request, )` - -The `onFetch` handler processes HTTP requests sent to your actor. It receives the actor context and a standard `Request` object. - -WebSocket upgrades are not currently supported in `onFetch`. Use `onWebSocket` instead. - -```typescript -const httpActor = actor(, - actions: , - onFetch(ctx, request) ), , - }); - } - - if (url.pathname === "/api/echo" && request.method === "POST") ); - } - - // Return 404 for unhandled paths - return new Response("Not Found", ); - }, -}); -``` - -```typescript -function buildRouter(ctx: ActorContext) ); - }); - - app.post("/api/echo", async (c) => ); - - app.get("/api/stats", (c) => ); - }); - - return app; -} - -const honoActor = actor(, - createVars(ctx) ; - }, - actions: , - async onFetch(ctx, request) , -}); -``` - -Also see the [raw fetch handler example project](https://github.com/rivet-dev/rivetkit/tree/main/examples/raw-fetch-handler). - - `onFetch` can be used to expose Server-Sent Events from Rivet Actors. - -### `onWebSocket(c, websocket, )` - -The `onWebSocket` handler manages WebSocket connections. It receives the actor context, a `WebSocket` object, and the initial `Request`. - -```typescript -const websocketActor = actor(, - actions: , - onWebSocket(ctx, websocket) )); - - websocket.addEventListener("message", (event) => ); - }, -}); -``` - -Also see the [raw WebSocket handler with proxy example project](https://github.com/rivet-dev/rivetkit/tree/main/examples/raw-websocket-handler-proxy). - - Connection lifecycle hooks like `onConnect` and `onDisconnect` do not get called when opening WebSockets for `onWebSocket`. This is because `onWebSocket` provides a low-level connection. Use `ws.addEventListener("open")` and `ws.addEventListener("close")` instead. - -## Accessing Your Handlers - -There are three ways to access your actor's fetch and WebSocket handlers: - -### Option A: From Backend via RivetKit Client - -You can use the RivetKit client's built-in methods for raw HTTP and WebSocket access: - -```typescript -const client = createClient("http://localhost:8080"); - -// HTTP requests using .fetch() method -const actor = client.myActor.getOrCreate(["key"]); -const response = await actor.fetch("/api/hello", ); -const data = await response.json(); - -// POST request with JSON body -const postResponse = await actor.fetch("/api/echo", , - body: JSON.stringify(), -}); -``` - -```typescript -const client = createClient("http://localhost:8080"); - -// WebSocket connections using .websocket() method -const actor = client.myActor.getOrCreate(["key"]); -const ws = await actor.websocket("/custom/path"); - -// Listen for messages -ws.addEventListener("message", (event) => else if (message.type === "echo") else if (message.type === "pong") -}); - -// Send messages -ws.send(JSON.stringify()); - -// Send ping -ws.send(JSON.stringify()); -``` - -For more advanced use cases, you can forward requests to actor handlers from your server: - -```typescript -const = registry.start(); - -const app = new Hono(); - -// Forward requests to actor's fetch handler -app.all("/forward/:name/*", async (c) => `, ""); - const url = new URL(truncatedPath, c.req.url); - const newRequest = new Request(url, c.req.raw); - - // Forward to actor's fetch handler - const actor = client.counter.getOrCreate(name); - const response = await actor.fetch(truncatedPath, newRequest); - - return response; -}); - -serve(app); -``` - -```typescript -const = registry.start(); - -const app = new Hono(); - -// Forward WebSocket connections to actor's WebSocket handler -app.get("/ws/:name", upgradeWebSocket(async (c) => ); - - actorWs.addEventListener("close", () => ); - }, - onMessage: (evt, ws) => , - onClose: (evt, ws) => , - }; -})); - -serve(app); -``` - -### Option B: From Frontend with RivetKit Client - -Use the RivetKit client to make direct HTTP requests or WebSocket connections: - -```typescript -const client = createClient("http://localhost:8080"); - -// HTTP requests -const actor = client.myActor.getOrCreate(["key"]); -const response = await actor.fetch("/api/hello", ); -const data = await response.json(); -console.log(data); // - -// POST request with data -const postResponse = await actor.fetch("/api/echo", , - body: JSON.stringify(), -}); - -// Handle response -if (postResponse.ok) else -``` - -```typescript +```typescript } const client = createClient("http://localhost:8080"); -// WebSocket connections -const actor = client.myActor.getOrCreate(["key"]); -const ws = await actor.websocket("/"); - -// Listen for messages -ws.addEventListener("message", (event) => ); - break; - - case "echo": - console.log("Echo received:", message.data); - displayMessage(message.data); - break; - - case "pong": - console.log("Pong received, latency:", Date.now() - message.timestamp); - break; - - case "error": - console.error("Error:", message.message); - break; - } +// Create user +const alice = await client.userActor.create("alice", }); -// Send messages -function sendMessage(text) )); -} - -// Ping for latency testing -function ping() )); -} +alice.updateUser("alice2@example.com"); -// Handle connection errors -ws.addEventListener("error", (event) => ); +const userData = await alice.getUser(); +console.log("User data:", userData); -ws.addEventListener("close", () => ); +// Create another user +const bob = await client.userActor.create("bob", +}); +const bobData = await bob.getUser(); ``` - The `.websocket()` method returns a barebones WebSocket. Unlike [actor connections](/docs/actors/connections), it does not provide automatic reconnection logic. You must implement reconnection logic yourself if needed. +### Using Drizzle ORM -### Option C: From Frontend via Direct RivetKit Router Access +Here's the same user actor pattern using Drizzle ORM for more type-safe database operations: -You can access your actor handlers directly through the mounted RivetKit router. The router automatically handles the required headers for authentication and routing. +```typescript } +interface ActorInput -For HTTP requests, the router expects these headers: -- `X-RivetKit-Actor-Query`: JSON-encoded actor query -- `X-RivetKit-Encoding`: Encoding type (usually "json") -- `X-RivetKit-Conn-Params`: JSON-encoded connection parameters (optional) +// Define your schema +const users = pgTable("users", ); -```typescript -// Direct HTTP request to actor -const response = await fetch("http://localhost:8080/registry/actors/myActor/request/api/hello", - }), - "X-RivetKit-Encoding": "json", - "X-RivetKit-Conn-Params": JSON.stringify() - } -}); +// Create a database connection +const pool = new Pool(); -const data = await response.json(); -console.log(data); // +// Initialize Drizzle with the pool +const db = drizzle(pool); -// POST request with data -const postResponse = await fetch("http://localhost:8080/registry/actors/myActor/request/api/echo", - }), - "X-RivetKit-Encoding": "json", - "X-RivetKit-Conn-Params": JSON.stringify(), - "Content-Type": "application/json" +// Create the user actor +const userActor = actor(), + + // Insert user into database when actor starts + onWake: async (c, opts) => ); + }, + + actions: ) + .where(eq(users.username, c.state.username)); + + return ; }, - body: JSON.stringify() -}); - -// Handle response -if (postResponse.ok) else -``` - -For WebSocket connections, authentication data is passed via WebSocket subprotocols: - -```typescript -// Direct WebSocket connection to actor -const protocols = [ - `query.$ - }))}`, - `encoding.json`, - `conn_params.$))}` -]; - -const ws = new WebSocket("ws://localhost:8080/registry/actors/myActor/ws/", protocols); - -// Listen for messages -ws.addEventListener("message", (event) => ); - - // Send initial message - ws.send(JSON.stringify()); - break; - - case "echo": - console.log("Echo received:", message.data); - break; - - case "pong": - console.log("Pong received, latency:", Date.now() - message.timestamp); - break; - - case "error": - console.error("WebSocket error:", message.message); - break; + + // Get user data + getUser: async (c) => ; } + } }); -// Send ping for latency testing -function sendPing() )); -} - -// Handle connection events -ws.addEventListener("open", () => ); - -ws.addEventListener("error", (event) => ); - -ws.addEventListener("close", (event) => ); +const registry = setup(, +}); ``` - For Cloudflare Workers, you must include `"rivetkit"` as a protocol when using raw WebSockets: - - ```typescript - const protocols = [ - "rivetkit", // Required for Cloudflare Workers - `query.$ - }))}`, - `encoding.json` - ]; - ``` - -## Authentication - -If you are using the external client, authentication is handled through the `onAuth` handler. The `onAuth` handler is executed on the server before the request is sent to the actor, reducing resource load on the actor by filtering out unauthorized requests early. - -If you are using the server-side client, then authentication is skipped by default. - -See the [authentication documentation](/docs/actors/authentication) for detailed information on implementing authentication patterns. +```typescript } +const client = createClient("http://localhost:8080"); -## State Saves +// Create user +const alice = await client.userActor.create("alice", +}); -State changes in `onFetch` and `onWebSocket` handlers are automatically saved after the handler finishes executing. +alice.updateUser("alice2@example.com"); -For `onWebSocket` handlers specifically, you'll need to manually save state using `c.saveState()` while the WebSocket connection is open if you want state changes to be persisted immediately. This is because WebSocket connections can remain open for extended periods, and state changes made during event handlers (like `message` events) won't be automatically saved until the connection closes. +const userData = await alice.getUser(); +console.log("User data:", userData); -```typescript -const websocketActor = actor(, - actions: , - onWebSocket(ctx, websocket) )); - }); - }, +// Create another user +const bob = await client.userActor.create("bob", }); +const bobData = await bob.getUser(); ``` +## Fetch and WebSocket Handler -For more details on state management, see [State](/docs/actors/state). - -## W3C Compliance - -It's not possible to use the global `fetch` method or global WebSocket class to connect to an actor. This is because actors do not have traditional network interfaces to communicate with. +# Fetch and WebSocket Handler -However, the `Request`, `Response`, and `WebSocket` types used with `.fetch()` and `.websocket()` comply with the W3C specification and will work wherever you pass them. +These docs have moved to [Low-Level WebSocket Handler](/docs/actors/websocket-handler) and [Low-Level Request Handler](/docs/actors/request-handler). ## Helper Types # Helper Types @@ -1867,42 +1492,25 @@ const counterWithProcessing = actor(, function processCounterAction(context: ActionContextOf) ``` +## Vanilla HTTP API + +# Vanilla HTTP API + +TODO ## Overview # Overview Actors for long-lived processes with durable state, realtime, and hibernate when not in use. -## Quickstart - - Set up Rivet with Node.js, Bun, and web frameworks - - Set up Rivet with React - - Set up Rivet with Next.js - - Set up Rivet with Cloudflare Workers - ## Features - **Long-Lived, Stateful Compute**: Each unit of compute is like a tiny server that remembers things between requests – no need to re-fetch data from a database or worry about timeouts. Like AWS Lambda, but with memory and no timeouts. - **Blazing-Fast Reads & Writes**: State is stored on the same machine as your compute, so reads and writes are ultra-fast. No database round trips, no latency spikes. -- **Realtime**: Update state and broadcast changes in realtime with WebSockets or SSE. No external pub/sub systems, no polling – just built-in low-latency events. +- **Realtime**: Update state and broadcast changes in realtime with WebSockets. No external pub/sub systems, no polling – just built-in low-latency events. - **Infinitely Scalable**: Automatically scale from zero to millions of concurrent actors. Pay only for what you use with instant scaling and no cold starts. - **Fault Tolerant**: Built-in error handling and recovery. Actors automatically restart on failure while preserving state integrity and continuing operations. -## Use Cases - -Actors are perfect for applications that need persistent state and real-time updates: - -- **AI agents**: Stateful AI assistants with conversation history -- **Collaborative documents**: Multiple users editing documents simultaneously (Yjs integration) -- **Local-first sync**: Offline-first applications with server synchronization -- **Per-tenant databases**: Isolated data stores for each user or tenant -- **Background job**: Background & time-based task execution with persistent state -- **Rate limiting**: Distributed rate limiting with persistent counters -- **Stream processing**: Real-time data processing with persistent state - ## Core Concepts ### State Management @@ -1950,7 +1558,7 @@ Learn more about [actions](/docs/actors/actions) and [communicating with actors] ### Real-time Communication & Events -Actors support real-time bidirectional communication through WebSocket and SSE connections. Clients can establish persistent connections to receive live updates. +Actors support real-time bidirectional communication through WebSocket connections. Clients can establish persistent connections to receive live updates. For example, to send events to all connected clients: @@ -2020,24 +1628,6 @@ const user = await manager.createUser("Alice"); const foundUser = await manager.getUser(user.userId); // Type: | undefined ``` - -## Frequently Asked Questions - - Some software makes sense to separate – e.g., for data lakes or highly relational data. But at the end of the day, data has to be partitioned somewhere at some point. - - Usually "faster" databases like Cassandra, DynamoDB, or Vitess make consistency tradeoffs to get better performance. Stateful serverless forces you to think about how your data is sharded for better performance, better scalability, and less consistency footguns. - - See [Sharing and Joining State](/docs/actors/sharing-and-joining-state) for detailed strategies on combining data from multiple actors. - - OLAP, data lakes, graph databases, and highly relational data are currently not ideal use cases for the actor model. - - Yes, but only in the same way that storing data in a single database row creates a bottleneck. - - Just like a single database row can cause contention when multiple clients try to read and write the same data, a single actor can become a bottleneck if too many requests target it. - - The solution is the same: shard your data across multiple actors to distribute the load and scale seamlessly. - - However, actors handle much higher throughput than traditional database rows because they keep data in memory, making read and write operations significantly faster. ## Input Parameters # Input Parameters @@ -2277,69 +1867,86 @@ Actors follow a well-defined lifecycle with hooks at each stage. Understanding t Actor lifecycle hooks are defined as functions in the actor configuration. -### `createState` and `state` +### `state` + +The `state` constant defines the initial state of the actor. See [state documentation](/docs/actors/state) for more information. -The `createState` function or `state` constant defines the initial state of the actor (see [state documentation](/docs/actors/state)). The `createState` function is called only once when the actor is first created. +```typescript +const counter = actor(, + actions: +}); +``` -### `createVars` and `vars` +### `createState` -The `createVars` function or `vars` constant defines ephemeral variables for the actor (see [state documentation](/docs/actors/state)). These variables are not persisted and are useful for storing runtime-only objects or temporary data. +`createState(c: ActorContext, input: TInput): TState | Promise` -The `createVars` function can also receive driver-specific context as its second parameter, allowing access to driver capabilities like Rivet KV or Cloudflare Durable Object storage. +The `createState` function dynamically initializes state based on input. Called only once when the actor is first created. Can be async. See [state documentation](/docs/actors/state) for more information. ```typescript -// In this example, assume we're using Redis -// Using vars constant -const counter1 = actor(, - vars: , +const counter = actor() => (), actions: }); +``` -// Using createVars function -const counter2 = actor(, - createVars: () => ; - }, +### `vars` + +The `vars` constant defines ephemeral variables for the actor. These variables are not persisted and are useful for storing runtime-only data. The value for `vars` must be clonable via `structuredClone`. See [ephemeral variables documentation](/docs/actors/state#ephemeral-variables-vars) for more information. + +```typescript +const counter = actor(, + vars: , actions: }); +``` -// Access driver-specific context -const exampleActor = actor(, - // Access driver context in createVars - createVars: (c: ActorInitContext, driverCtx: DriverContext) => (), +### `createVars` + +`createVars(c: InitContext, driverCtx: any): TVars | Promise` + +The `createVars` function dynamically initializes ephemeral variables. Can be async. Use this when you need to initialize values at runtime. The `driverCtx` parameter provides driver-specific context. See [ephemeral variables documentation](/docs/actors/state#ephemeral-variables-vars) for more information. + +```typescript +interface CounterVars + +const counter = actor(, + createVars: (c, driverCtx): CounterVars => (), actions: - } }); ``` ### `onCreate` -The `onCreate` hook is called at the same time as `createState`, but unlike `createState`, it doesn't return any value. Use this hook for initialization logic that doesn't affect the initial state. +`onCreate(c: ActorContext, input: TInput): void | Promise` + +The `onCreate` hook is called when the actor is first created. Can be async. Use this hook for initialization logic that doesn't affect the initial state. ```typescript -// Using state constant -const counter1 = actor(, - actions: -}); +const counter = actor(, + + onCreate: (c, input: ) => , -// Using createState function -const counter2 = actor(; - }, actions: }); +``` -// Using onCreate -const counter3 = actor(, - - // Run initialization logic (logging, external service setup, etc.) - onCreate: (c, opts, input: ) => , - +### `onDestroy` + +`onDestroy(c: ActorContext): void | Promise` + +The `onDestroy` hook is called when the actor is being permanently destroyed. Can be async. Use this for final cleanup operations like closing external connections, releasing resources, or performing any last-minute state persistence. + +```typescript +const gameSession = actor(, actions: }); ``` -### `onStart` +### `onWake` -This hook is called any time the actor is started (e.g. after restarting, upgrading code, or crashing). +`onWake(c: ActorContext): void | Promise` + +This hook is called any time the actor is started (e.g. after restarting, upgrading code, or crashing). Can be async. This is called after the actor has been initialized but before any connections are accepted. @@ -2348,26 +1955,53 @@ Use this hook to set up any resources or start any background tasks, such as `se ```typescript const counter = actor(, vars: , - - onStart: (c) => , 10000); - + + onWake: (c) => , 10000); + // Store interval ID in vars to clean up later if needed c.vars.intervalId = intervalId; }, - + actions: } } }); ``` +### `onSleep` + +`onSleep(c: ActorContext): void | Promise` + +This hook is called when the actor is going to sleep. Can be async. Use this to clean up resources, close connections, or perform any shutdown operations. + +Not supported on all platforms. + +```typescript +const counter = actor(, + vars: , + + onWake: (c) => , 10000); + }, + + onSleep: (c) => + + // Perform any other cleanup + console.log('Final count:', c.state.count); + }, + + actions: +}); +``` + ### `onStateChange` -Called whenever the actor's state changes. This is often used to broadcast state updates. +`onStateChange(c: ActorContext, newState: TState): void` + +Called whenever the actor's state changes. Cannot be async. This is often used to broadcast state updates. ```typescript const counter = actor(, - + onStateChange: (c, newState) => ); }, @@ -2378,33 +2012,37 @@ const counter = actor(, ### `createConnState` and `connState` +`createConnState(c: CreateConnStateContext, params: TConnParams): TConnState | Promise` + There are two ways to define the initial state for connections: 1. `connState`: Define a constant object that will be used as the initial state for all connections -2. `createConnState`: A function that dynamically creates initial connection state based on connection parameters +2. `createConnState`: A function that dynamically creates initial connection state based on connection parameters. Can be async. ### `onBeforeConnect` -The `onBeforeConnect` hook is called whenever a new client connects to the actor. Clients can pass parameters when connecting, accessible via `params`. This hook is used for connection validation and can throw errors to reject connections. +`onBeforeConnect(c: OnBeforeConnectContext, params: TConnParams): void | Promise` + +The `onBeforeConnect` hook is called whenever a new client connects to the actor. Can be async. Clients can pass parameters when connecting, accessible via `params`. This hook is used for connection validation and can throw errors to reject connections. The `onBeforeConnect` hook does NOT return connection state - it's used solely for validation. ```typescript const chatRoom = actor(, - + // Method 1: Use a static default connection state connState: , - + // Method 2: Dynamically create connection state - createConnState: (c, opts, params: ) => ; + createConnState: (c, params: ) => ; }, - + // Validate connections before accepting them - onBeforeConnect: (c, opts, params: ) => - + onBeforeConnect: (c, params: ) => + // Authentication is valid, connection will proceed // The actual connection state will come from connState or createConnState }, - + actions: }); ``` @@ -2413,19 +2051,21 @@ Connections cannot interact with the actor until this method completes successfu ### `onConnect` -Executed after the client has successfully connected. +`onConnect(c: OnConnectContext, conn: Conn): void | Promise` + +Executed after the client has successfully connected. Can be async. Receives the connection object as a second parameter. ```typescript const chatRoom = actor(, messages: [] }, - - onConnect: (c) => ; - + + onConnect: (c, conn) => ; + // Broadcast that a user joined c.broadcast("userJoined", ); - + console.log(`User $ connected`); }, - + actions: }); ``` @@ -2434,50 +2074,60 @@ Messages will not be processed for this actor until this hook succeeds. Errors t ### `onDisconnect` -Called when a client disconnects from the actor. Use this to clean up any connection-specific resources. +`onDisconnect(c: ActorContext, conn: Conn): void | Promise` + +Called when a client disconnects from the actor. Can be async. Receives the connection object as a second parameter. Use this to clean up any connection-specific resources. ```typescript const chatRoom = actor(, messages: [] }, - - onDisconnect: (c) => - + + onDisconnect: (c, conn) => + // Broadcast that a user left c.broadcast("userLeft", ); - + console.log(`User $ disconnected`); }, - + actions: }); ``` -### `onFetch` +### `onRequest` + +`onRequest(c: RequestContext, request: Request): Response | Promise` -The `onFetch` hook handles HTTP requests sent to your actor. It receives the actor context and a standard `Request` object, and should return a `Response` object or `void` to continue default routing. +The `onRequest` hook handles HTTP requests sent to your actor at `/actors//http/*` endpoints. Can be async. It receives the request context and a standard `Request` object, and should return a `Response` object or `void` to continue default routing. + +See [Request Handler](/docs/actors/request-handler) for more details. ```typescript const apiActor = actor(, - - onFetch: (c, request) => ), + + onRequest: (c, request) => ), }); } - + // Return void to continue to default routing return; }, - + actions: }); ``` ### `onWebSocket` -The `onWebSocket` hook handles WebSocket connections to your actor. It receives the actor context, a `WebSocket` object, and the initial `Request`. Use this to set up WebSocket event listeners and handle real-time communication. +`onWebSocket(c: ActorContext, websocket: WebSocket): void | Promise` + +The `onWebSocket` hook handles WebSocket connections to your actor. Can be async. It receives the actor context and a `WebSocket` object. Use this to set up WebSocket event listeners and handle real-time communication. + +See [WebSocket Handler](/docs/actors/websocket-handler) for more details. ```typescript const realtimeActor = actor(, - - onWebSocket: (c, websocket, request) => )); + + onWebSocket: (c, websocket) => )); // Handle incoming messages websocket.addEventListener("message", (event) => )); @@ -2492,47 +2142,15 @@ const realtimeActor = actor(, }); ``` -### `onAuth` - -The `onAuth` hook is called on the HTTP server before clients can interact with the actor. This hook is required for any public HTTP endpoint access and is used to validate client credentials and return authentication data that will be available on connections. - -This hook runs on the HTTP server (not the actor) to reduce load and prevent denial of service attacks against individual actors. Only called for public endpoints - calls to actors from within the backend do not trigger this handler. - -```typescript -const secureActor = actor() => - - const token = authHeader.slice(7); - - // Validate token with your auth service - const user = await validateAuthToken(token); - if (!user) - - // Return auth data (must be serializable) - return ; - }, - - state: }, - - onConnect: (c) => with role $ connected`); - - c.state.activeUsers[userId] = ; - }, - - actions: - - return ; - } - } -}); -``` - ### `onBeforeActionResponse` -The `onBeforeActionResponse` hook is called before sending an action response to the client. Use this hook to modify or transform the output of an action before it's sent to the client. This is useful for formatting responses, adding metadata, or applying transformations to the output. +`onBeforeActionResponse(c: ActorContext, name: string, args: unknown[], output: TOutput): TOutput | Promise` + +The `onBeforeActionResponse` hook is called before sending an action response to the client. Can be async. Use this hook to modify or transform the output of an action before it's sent to the client. This is useful for formatting responses, adding metadata, or applying transformations to the output. ```typescript const loggingActor = actor(, - + onBeforeActionResponse: (c, actionName, args, output) => called with args:`, args); console.log(`Action $ returned:`, output); @@ -2552,9 +2170,34 @@ const loggingActor = actor(, }); ``` -## Destroying Actors +## Options + +The `options` object allows you to configure various timeouts and behaviors for your actor. + +```typescript +const myActor = actor(, + + options: , -_Destroying actors is not available yet._ + actions: +}); +``` + +| Option | Default | Description | +|--------|---------|-------------| +| `createVarsTimeout` | 5000ms | Timeout for `createVars` function | +| `createConnStateTimeout` | 5000ms | Timeout for `createConnState` function | +| `onConnectTimeout` | 5000ms | Timeout for `onConnect` hook | +| `onSleepTimeout` | 5000ms | Timeout for `onSleep` hook | +| `onDestroyTimeout` | 5000ms | Timeout for `onDestroy` hook | +| `stateSaveInterval` | 10000ms | Interval for persisting state | +| `actionTimeout` | 60000ms | Timeout for action execution | +| `waitUntilTimeout` | 15000ms | Max time to wait for background promises during shutdown | +| `connectionLivenessTimeout` | 2500ms | Timeout for connection liveness check | +| `connectionLivenessInterval` | 5000ms | Interval for connection liveness check | +| `noSleep` | false | Prevent actor from sleeping | +| `sleepTimeout` | 30000ms | Time before actor sleeps due to inactivity | +| `canHibernateWebSocket` | false | Whether WebSockets can hibernate (experimental) | ## Advanced @@ -2591,7 +2234,7 @@ When extracting logic from lifecycle hooks or actions into external functions, y const myActor = actor(, // Use external function in lifecycle hook - onStart: (c) => logActorStarted(c) + onWake: (c) => logActorStarted(c) }); // Simple external function with typed context @@ -2606,59 +2249,48 @@ See [Helper Types](/docs/actors/helper-types) for more details on using `ActorCo ```typescript interface CounterInput -const counter = actor( - - const token = authHeader.slice(7); - const user = await validateAuthToken(token); - if (!user) - - return ; - }, - - // Initialize state with input - createState: (c: ActorInitContext, input: CounterInput) => (), - +interface CounterState + +interface ConnParams + +interface ConnState + +const counter = actor(), + // Initialize actor (run setup that doesn't affect initial state) - onCreate: (c, opts, input: ) => " initialized`); + onCreate: (c, input: CounterInput) => " initialized`); // Set up external resources, logging, etc. }, - - // Define default connection state - connState: , - - createConnState: (c, opts) => ; + + // Dynamically create connection state from params + createConnState: (c, params: ConnParams): ConnState => ; }, - + // Lifecycle hooks - onStart: (c) => " started with count:`, c.state.count); + onWake: (c) => " started with count:`, c.state.count); }, - + onStateChange: (c, newState) => ); }, - - onBeforeConnect: (c, ) => attempting to connect`); + + onBeforeConnect: (c, params: ConnParams) => + console.log(`User $ attempting to connect`); }, - - onConnect: (c) => connected to "$"`); + + onConnect: (c, conn) => connected to "$"`); }, - - onDisconnect: (c) => disconnected from "$"`); + + onDisconnect: (c, conn) => disconnected from "$"`); }, - + // Transform all action responses onBeforeActionResponse: (c, actionName, args, output) => }; }, - + // Define actions actions: , - - reset: (c) => - - c.state.count = 0; - return c.state.count; - }, - + getInfo: (c) => (), } }); @@ -2856,7 +2488,7 @@ await connection.increment(1); See the [JavaScript client documentation](/docs/clients/javascript) for more information. ```tsx } -const = createRivetKit("http://localhost:8080"); +const = createRivetKit(); function Counter() ); @@ -2916,17 +2548,25 @@ const registry = setup(, Choose your preferred web framework: +```ts } +// The `/rivet` endpoint is automatically exposed here for external clients +const = createHandler(registry); +; +``` + ```ts } const app = new Hono } }>(); app.post("/increment/:name", async (c) => ); }); +// The `/rivet` endpoint is automatically exposed here for external clients const = createHandler(registry, ); ; ``` ```ts } +// The `/rivet` endpoint is automatically mounted on this router for external clients const = createHandler(registry, ), , }); } @@ -2938,7 +2578,23 @@ const = createHandler(registry, ), , ; ``` -The `/rivet` endpoint is automatically mounted by Rivet and is required for client communication. The Cloudflare Workers driver handles this automatically. This can be configured with `managerPath`. +```ts } +const = createInlineClient(registry); + +// IMPORTANT: Your Durable Object must be exported here +; + +default ), , + }); + } + + // Optional: Mount /rivet path to access actors from external clients + if (url.pathname.startsWith("/rivet")) + + return new Response("Not Found", ); + }, +} satisfies ExportedHandler; +``` Configure your `wrangler.json` for Cloudflare Workers: @@ -2985,7 +2641,7 @@ wrangler deploy Your actors will now run on Cloudflare's edge with persistent state backed by Durable Objects. -See the [Cloudflare Workers deployment guide](/docs/deploy/cloudflare-workers) for detailed deployment instructions and configuration options. +See the [Cloudflare Workers deployment guide](/docs/connect/cloudflare-workers) for detailed deployment instructions and configuration options. ## Configuration Options @@ -3127,7 +2783,7 @@ Import the `Counter` component in your page or layout to use it. For more examples on connecting to your actors using React, check the [React documentation for RivetKit](/docs/clients/react). -See the [Vercel deployment guide](/docs/deploy/vercel) for detailed instructions on deploying your RivetKit app to Vercel. +See the [Vercel deployment guide](/docs/connect/vercel) for detailed instructions on deploying your RivetKit app to Vercel. ## API Reference @@ -3164,8 +2820,7 @@ registry.start(); Set up your React application: ```tsx } -const client = createClient(); -const = createRivetKit(client); +const = createRivetKit(); function App() ); @@ -3228,6 +2883,127 @@ See [backend quickstart](/docs/actors/quickstart/backend) for more information. ## API Reference For detailed information about the React client API, see the [React Client API Reference](/docs/clients/react). +## Low-Level HTTP Request Handler + +# Low-Level HTTP Request Handler + +Actors can handle HTTP requests through the `onRequest` handler. + +For most use cases, [actions](/docs/actors/actions) provide high-level API powered by HTTP that's easier to work with than low-level HTTP. However, low-level handlers are required when implementing custom use cases or integrating external libraries that need direct access to the underlying HTTP `Request`/`Response` objects or WebSocket connections. + +## Handling HTTP Requests + +The `onRequest` handler processes HTTP requests sent to your actor. It receives the actor context and a standard `Request` object and returns a `Response` object. + +```typescript +const counterActor = actor(, + // WinterTC compliant - accepts standard Request and returns standard Response + onRequest: (c, request) ); + } + + if (request.method === "POST" && url.pathname === "/increment") ); + } + + return new Response("Not Found", ); + }, +}); +``` + +```typescript +function buildRouter(c: ActorContext) ); + }); + + app.post("/increment", (c) => ); + }); + + return app; +} + +const counterActor = actor(, + createVars: (c) => ; + }, + async onRequest: (c, request) , +}); +``` + +See also the [raw fetch handler example](https://github.com/rivet-dev/rivetkit/tree/main/examples/raw-fetch-handler). + +## Sending Requests To Actors + +### Via RivetKit Client + +Use the `.fetch()` method on an actor handle to send HTTP requests to the actor's `onRequest` handler. This can be executed from either your frontend or backend. + +```typescript +const client = createClient(); + +const actor = client.counter.getOrCreate("my-counter"); + +// .fetch() is WinterTC compliant, it accepts standard Request and returns standard Response +const response = await actor.fetch("/increment", ); +const data = await response.json(); +console.log(data); // +``` + +### Via HTTP API + +This handler can be accessed with raw HTTP using `https://api.rivet.dev/gateway//request/`. + +For example, to call `POST /increment` on the counter actor above: + +```typescript +const response = await fetch( + `https://api.rivet.dev/gateway/$/request/increment`, + `, + }, + } +); +const data = await response.json(); +console.log(data); // +``` + +```bash +curl -X POST "https://api.rivet.dev/gateway//request/increment" \ + -H "Authorization: Bearer " +``` + +The request is routed to the actor's `onRequest` handler where: + +- `request.method` is `"POST"` +- `request.url` ends with `/increment` (the path after `/request/`) +- Headers, body, and other request properties are passed through unchanged + +See the [HTTP API reference](/docs/actors/http-api) for more information on HTTP routing and authentication. + +### Via Proxying Requests + +You can proxy HTTP requests from your own server to actor handlers using the RivetKit client. This is useful when you need to add custom authentication, rate limiting, or request transformation before forwarding to actors. + +```typescript +const client = createClient(); + +const app = new Hono(); + +// Proxy requests to actor's onRequest handler +app.all("/actors/:id/:path", async (c) => ); + +serve(app); +``` + +## Connection & Lifecycle Hooks + +`onRequest` will trigger the `onBeforeConnect`, `onConnect`, and `onDisconnect` hooks. Read more about [lifecycle hooks](/docs/actors/lifecycle). + +Requests in flight will be listed in `c.conns`. Read more about [connections](/docs/actors/connections). + +## WinterTC Compliance + +The `onRequest` handler is WinterTC compliant and will work with existing libraries using the standard `Request` and `Response` types. + +## Limitations + +- Does not support streaming responses & server-sent events at the moment. See the [tracking issue](https://github.com/rivet-dev/rivet/issues/3529). +- `OPTIONS` requests currently are handled by Rivet and are not passed to `onRequest` ## Scaling & Concurrency # Scaling & Concurrency @@ -3657,6 +3433,155 @@ The `setupTest` function automatically calls `vi.useFakeTimers()`, allowing you 4. **Use realistic data**: Test with data that resembles production scenarios. Rivet's testing framework automatically handles server setup and teardown, so you can focus on writing effective tests for your business logic. +## Low-Level WebSocket Handler + +# Low-Level WebSocket Handler + +Actors can handle WebSocket connections through the `onWebSocket` handler. + +For most use cases, [actions](/docs/actors/actions) and [events](/docs/actors/events) provide high-level connection handling powered by WebSockets that's easier to work with than low-level WebSockets. However, low-level handlers are required when implementing custom use cases. + +## Handling WebSocket Connections + +The `onWebSocket` handler manages low-level WebSocket connections. It receives the actor context and a `WebSocket` object. + +```typescript +const chatActor = actor(, + onWebSocket: (c, websocket) )); + }); + + websocket.addEventListener("message", (event) => ); + }, +}); +``` + +See also the [raw WebSocket handler example](https://github.com/rivet-dev/rivetkit/tree/main/examples/raw-websocket-handler). + +## Connecting To Actors + +### Via RivetKit Client + +Use the `.websocket()` method on an actor handle to open a WebSocket connection to the actor's `onWebSocket` handler. This can be executed from either your frontend or backend. + +```typescript +const client = createClient(); + +const actor = client.chat.getOrCreate("my-chat"); + +// Open WebSocket connection +const ws = await actor.websocket("/"); + +// Listen for messages +ws.addEventListener("message", (event) => ); + +// Send messages +ws.send(JSON.stringify()); +``` + +The `.websocket()` method returns a standard WebSocket. + +### Via HTTP API + +This handler can be accessed with raw WebSockets using `wss://api.rivet.dev/gateway/@/websocket/`. + +For example, to connect to the chat actor above: + +```typescript +const ws = new WebSocket( + `wss://api.rivet.dev/gateway/$@$/websocket/` +); + +ws.addEventListener("message", (event) => ); + +ws.addEventListener("open", () => )); +}); +``` + +```bash +wscat -c "wss://api.rivet.dev/gateway/@/websocket/" +``` + +The path after `/websocket/` is passed to your `onWebSocket` handler and can be used to route to different functionality within your actor. For example, to connect with a custom path `/admin`: + +```typescript +const ws = new WebSocket( + `wss://api.rivet.dev/gateway/$@$/websocket/admin` +); +``` + +```bash +wscat -c "wss://api.rivet.dev/gateway/@/websocket/admin" +``` + +See the [HTTP API reference](/docs/actors/http-api) for more information on WebSocket routing and authentication. + +### Via Proxying Connections + +You can proxy WebSocket connections from your own server to actor handlers using the RivetKit client. This is useful when you need to add custom authentication or connection management before forwarding to actors. + +```typescript +const client = createClient(); + +const app = new Hono(); + +// Proxy WebSocket connections to actor's onWebSocket handler +app.get("/ws/:id", upgradeWebSocket(async (c) => ); + actorWs.addEventListener("close", () => ); + }, + onMessage: (evt, ws) => , + onClose: () => , + }; +})); + +default app; +``` + +See also the [raw WebSocket handler with proxy example](https://github.com/rivet-dev/rivetkit/tree/main/examples/raw-websocket-handler-proxy). + +## Connection & Lifecycle Hooks + +`onWebSocket` will trigger the `onBeforeConnect`, `onConnect`, and `onDisconnect` hooks. Read more about [lifecycle hooks](/docs/actors/lifecycle). + +Open WebSockets will be listed in `c.conns`. `conn.send` and `c.broadcast` have no effect on low-level WebSocket connections. Read more about [connections](/docs/actors/connections). + +## WinterTC Compliance + +The `onWebSocket` handler uses standard WebSocket APIs and will work with existing libraries expecting WinterTC-compliant WebSocket objects. + +## Advanced + +## WebSocket Hibernation + +WebSocket hibernation allows actors to go to sleep while keeping WebSocket connections alive. Actors automatically wake up when a message is received or the connection closes. + +Enable hibernation by setting `canHibernateWebSocket: true`. You can also pass a function `(request) => boolean` for conditional control. + +```typescript +const myActor = actor(, +}); +``` + +Since `open` only fires once when the client first connects, use `c.conn.state` to store per-connection data that persists across sleep cycles. See [connections](/docs/actors/connections) for more details. + +### Accessing the Request + +The underlying HTTP request is available via `c.request`. This is useful for accessing the path or query parameters. + +```typescript +onWebSocket: (c, websocket) +``` + +### Async Handlers + +The `onWebSocket` handler can be async, allowing you to perform async code before setting up event listeners: + +```typescript +onWebSocket: async (c, websocket) => )); + }); + + websocket.addEventListener("message", (event) => ); +} +``` ## Node.js & Bun # Node.js & Bun @@ -3706,18 +3631,17 @@ See the [React quickstart guide](/docs/actors/quickstart/react) for getting star ## API Reference -### `createRivetKit(client, options?)` +### `createRivetKit(endpoint?, options?)` Creates the Rivet hooks for React integration. ```tsx -const client = createClient(); -const = createRivetKit(client); +const = createRivetKit(); ``` #### Parameters -- `client`: The Rivet client created with `createClient` +- `endpoint`: Optional endpoint URL (defaults to `http://localhost:6420` or `process.env.RIVET_ENDPOINT`) - `options`: Optional configuration object #### Returns @@ -4011,7 +3935,11 @@ _AWS Lambda is coming soon_ Deploy your Cloudflare Workers + RivetKit app to [Cloudflare Workers](https://workers.cloudflare.com/). -Complete example Cloudflare Workers + RivetKit app. +Minimal Cloudflare Workers + RivetKit example. + +Cloudflare Workers with Hono router. + +Advanced setup using createInlineClient. ## Guide @@ -4240,7 +4168,16 @@ Your runner should appear as connected on the Rivet dashboard once the service r # Deploying to Hetzner -Please see the [VM & Bare Metal](/docs/deploy/vm-and-bare-metal) guide. +Please see the [VM & Bare Metal](/docs/connect/vm-and-bare-metal) guide. +## Deploy + +# Deploy + +Rivet supports deployment to a wide range of platforms, from serverless functions to self-hosted infrastructure. + + ))} + +))} ## Deploying to Kubernetes # Deploying to Kubernetes @@ -4522,7 +4459,6 @@ The File System driver is ideal for development and single-node deployments. For | --- | --- | | Horizontal scaling | No | | WebSockets | Yes | -| SSE | Yes | | Edge | No | | Scheduling | Yes | @@ -4581,7 +4517,6 @@ The Memory driver does not persist data between server restarts. For production | --- | --- | | Horizontal scaling | No | | WebSockets | Yes | -| SSE | Yes | | Edge | No | | Scheduling | Yes | @@ -4668,50 +4603,6 @@ This code block doesn't use autofill: const greeting = "Hello, World!"; console.log(greeting); ``` -## Architecture - -# Architecture - -Rivet supports three topologies that define how actors are distributed and scale. - - Each platform configures a default topology appropriate for that environment. In most cases, you can rely on these defaults unless you have specific distribution needs. - -## Configuration - -```typescript -const config = ; -``` - -## Types of Topologies - -### Standalone - -- **How it works**: Runs all actors in a single process -- **When to use**: Development, testing, simple apps with low traffic -- **Limitations**: No horizontal scaling, single point of failure -- **Default on**: Node.js, Bun - -### Partition - -- **How it works**: Each actor has its own isolated process. Clients connect directly to the actor for optimal performance. -- **When to use**: Production environments needing horizontal scaling -- **Limitations**: Minimal - balanced performance and availability for most use cases -- **Default on**: Rivet, Cloudflare Workers - -### Coordinate - -- **How it works**: Creates a peer-to-peer network between multiple servers with leader election with multiple actors running on each server. Clients connect to any server and data is transmitted to the leader over a pubsub server. -- **When to use**: High-availability scenarios needing redundancy and failover -- **Limitations**: Added complexity, performance overhead, requires external data source -- **Default on**: _None_ - -## Choosing a Topology - -In most cases, use your platform's default: - -1. **Standalone**: Simple, great for development -2. **Partition**: Best scaling & cost for production -3. **Coordinate**: Good for specialized deployment scenarios ## Cross-Origin Resource Sharing # Cross-Origin Resource Sharing @@ -5062,22 +4953,6 @@ Take full control of your Rivet deployment with flexible hosting options and sto Run Rivet actors on Cloudflare's edge computing platform Managed Rivet hosting with enterprise features and support -## System Architecture - -# System Architecture - - This document is for advanced users seeking to understand the internal architecture of RivetKit. Most users do not need to read this document. - -## Request Lifecycle - -### Base Architecture - -### Coordinated Architecture -## Webhooks - -# Webhooks - -TODO ## Overview # Overview @@ -5339,7 +5214,6 @@ Deploy Rivet Actors to Cloudflare Workers with Durable Objects for global edge c | --- | --- | | Horizontal scaling | Yes | | WebSockets | Yes | -| SSE | Yes | | Edge | Yes | | Scheduling | Yes | diff --git a/website/public/llms.txt b/website/public/llms.txt index a0f6df06be..543e6fc6aa 100644 --- a/website/public/llms.txt +++ b/website/public/llms.txt @@ -69,11 +69,14 @@ https://rivet.dev/docs/actors/authentication https://rivet.dev/docs/actors/clients https://rivet.dev/docs/actors/communicating-between-actors https://rivet.dev/docs/actors/connections +https://rivet.dev/docs/actors/destroy https://rivet.dev/docs/actors/ephemeral-variables +https://rivet.dev/docs/actors/errors https://rivet.dev/docs/actors/events https://rivet.dev/docs/actors/external-sql https://rivet.dev/docs/actors/fetch-and-websocket-handler https://rivet.dev/docs/actors/helper-types +https://rivet.dev/docs/actors/http-api https://rivet.dev/docs/actors/input https://rivet.dev/docs/actors/keys https://rivet.dev/docs/actors/lifecycle @@ -83,39 +86,39 @@ https://rivet.dev/docs/actors/quickstart/backend https://rivet.dev/docs/actors/quickstart/cloudflare-workers https://rivet.dev/docs/actors/quickstart/next-js https://rivet.dev/docs/actors/quickstart/react +https://rivet.dev/docs/actors/request-handler https://rivet.dev/docs/actors/scaling https://rivet.dev/docs/actors/schedule https://rivet.dev/docs/actors/sharing-and-joining-state https://rivet.dev/docs/actors/state https://rivet.dev/docs/actors/testing +https://rivet.dev/docs/actors/websocket-handler https://rivet.dev/docs/clients/javascript https://rivet.dev/docs/clients/next-js https://rivet.dev/docs/clients/openapi https://rivet.dev/docs/clients/react https://rivet.dev/docs/clients/rust -https://rivet.dev/docs/deploy/aws-ecs -https://rivet.dev/docs/deploy/aws-lambda -https://rivet.dev/docs/deploy/cloudflare-workers -https://rivet.dev/docs/deploy/freestyle -https://rivet.dev/docs/deploy/gcp-cloud-run -https://rivet.dev/docs/deploy/hetzner -https://rivet.dev/docs/deploy/kubernetes -https://rivet.dev/docs/deploy/railway -https://rivet.dev/docs/deploy/supabase -https://rivet.dev/docs/deploy/vercel -https://rivet.dev/docs/deploy/vm-and-bare-metal +https://rivet.dev/docs/connect +https://rivet.dev/docs/connect/aws-ecs +https://rivet.dev/docs/connect/aws-lambda +https://rivet.dev/docs/connect/cloudflare-workers +https://rivet.dev/docs/connect/freestyle +https://rivet.dev/docs/connect/gcp-cloud-run +https://rivet.dev/docs/connect/hetzner +https://rivet.dev/docs/connect/kubernetes +https://rivet.dev/docs/connect/railway +https://rivet.dev/docs/connect/supabase +https://rivet.dev/docs/connect/vercel +https://rivet.dev/docs/connect/vm-and-bare-metal https://rivet.dev/docs/drivers/build-your-own https://rivet.dev/docs/drivers/file-system https://rivet.dev/docs/drivers/memory https://rivet.dev/docs/examples/autofill-example -https://rivet.dev/docs/general/architecture https://rivet.dev/docs/general/cors https://rivet.dev/docs/general/docs-for-llms https://rivet.dev/docs/general/edge https://rivet.dev/docs/general/logging https://rivet.dev/docs/general/self-hosting -https://rivet.dev/docs/general/system-architecture -https://rivet.dev/docs/general/webhooks https://rivet.dev/docs/index https://rivet.dev/docs/integrations https://rivet.dev/docs/integrations/better-auth diff --git a/website/scripts/generateReadme.mjs b/website/scripts/generateReadme.mjs index 40d59a92f7..368d4d6271 100755 --- a/website/scripts/generateReadme.mjs +++ b/website/scripts/generateReadme.mjs @@ -22,7 +22,7 @@ Rivet Actors are a primitive of RivetKit provide everything you need to build fa - **Long-Lived, Stateful Compute**: Like AWS Lambda but with memory and no timeouts - **Blazing-Fast Reads & Writes**: State stored on same machine as compute -- **Realtime, Made Simple**: Built-in WebSockets and SSE support +- **Realtime, Made Simple**: Built-in WebSockets support - **Store Data Near Your Users**: Deploy to the edge for low-latency access - **Infinitely Scalable**: Auto-scale from zero to millions without configuration - **Fault Tolerant**: Automatic error handling and recovery built-in @@ -40,7 +40,7 @@ RivetKit provides everything you need to build fast, scalable, and real-time app - **Long-Lived, Stateful Compute**: Like AWS Lambda but with memory and no timeouts - **Blazing-Fast Reads & Writes**: State stored on same machine as compute -- **Realtime, Made Simple**: Built-in WebSockets and SSE support +- **Realtime, Made Simple**: Built-in WebSockets support - **Store Data Near Your Users**: Deploy to the edge for low-latency access - **Infinitely Scalable**: Auto-scale from zero to millions without configuration - **Fault Tolerant**: Automatic error handling and recovery built-in`; diff --git a/website/src/app/(v2)/(marketing)/(index)/components/PlatformIcons.tsx b/website/src/app/(v2)/(marketing)/(index)/components/PlatformIcons.tsx index 6f15c3d6fd..4637e580b2 100644 --- a/website/src/app/(v2)/(marketing)/(index)/components/PlatformIcons.tsx +++ b/website/src/app/(v2)/(marketing)/(index)/components/PlatformIcons.tsx @@ -158,25 +158,25 @@ export function PlatformIcons() { tooltip: "Cloudflare Durable Objects", }, { - href: "/docs/deploy/kubernetes", + href: "/docs/connect/kubernetes", src: kubernetesLogo, alt: "Kubernetes", tooltip: "Kubernetes", }, { - href: "/docs/deploy/aws-ecs", + href: "/docs/connect/aws-ecs", src: awsLogo, alt: "AWS ECS", tooltip: "AWS ECS", }, { - href: "/docs/deploy/gcp-cloud-run", + href: "/docs/connect/gcp-cloud-run", src: gcpLogo, alt: "GCP Cloud Run", tooltip: "GCP Cloud Run", }, { - href: "/docs/deploy/hetzner", + href: "/docs/connect/hetzner", src: hetznerLogo, alt: "Hetzner", tooltip: "Hetzner", diff --git a/website/src/app/(v2)/(marketing)/(index)/sections/TechSection.tsx b/website/src/app/(v2)/(marketing)/(index)/sections/TechSection.tsx index cb4f33e53e..c4ae8085b6 100644 --- a/website/src/app/(v2)/(marketing)/(index)/sections/TechSection.tsx +++ b/website/src/app/(v2)/(marketing)/(index)/sections/TechSection.tsx @@ -244,7 +244,7 @@ export function TechSection() { alt="Deno" /> + + Actors are private by default on Rivet Cloud. Only requests with the publishable token can interact with actors. -### onAuth Hook (Recommended) + - **Backend-only actors**: If your publishable token is only included in your backend, then authentication is not necessary. + - **Frontend-accessible actors**: If your publishable token is included in your frontend, then implementing authentication is recommended. + + + Actors are public by default on self-hosted Rivet. Anyone can access them without a token. -The `onAuth` hook runs on the HTTP server before clients can access actors. This is the preferred method for most authentication scenarios. + - **Only accessible within private network**: If Rivet is only accessible within your private network, then authentication is not necessary. + - **Rivet exposed to the public internet**: If Rivet is configured to accept traffic from the public internet, then implementing authentication is recommended. + + + +## Authentication Connections + +Authentication is configured through either: + +- `onBeforeConnect` for simple pass/fail validation +- `createConnState` when you need to access user data in your actions via `c.conn.state` + +### `onBeforeConnect` + +The `onBeforeConnect` hook validates credentials before allowing a connection. Throw an error to reject the connection. ```typescript import { actor, UserError } from "rivetkit"; +interface ConnParams { + authToken: string; +} + const chatRoom = actor({ - onAuth: async (params: { authToken?: string }, { request, intents }) => { - - // Extract token from params or headers - const token = params.authToken || request.headers.get("Authorization"); - - if (!token) { - throw new UserError("Authentication required"); + state: { messages: [] }, + + onBeforeConnect: async (c, params: ConnParams) => { + const roomName = c.key; + const isValid = await validateToken(params.authToken, roomName); + if (!isValid) { + throw new UserError("Forbidden", { code: "forbidden" }); } - - // Validate token and return user data - const user = await validateJWT(token); - return { - userId: user.id, - role: user.role, - permissions: user.permissions - }; }, - - state: { messages: [] }, - + actions: { sendMessage: (c, text: string) => { - // Access auth data via c.conn.auth - const { userId, role } = c.conn.auth; - - if (role !== "member") { - throw new UserError("Insufficient permissions"); - } - - const message = { - id: crypto.randomUUID(), - userId, - text, - timestamp: Date.now(), - }; - - c.state.messages.push(message); - c.broadcast("newMessage", message); - return message; - } - } + c.state.messages.push({ text, timestamp: Date.now() }); + }, + }, }); ``` -### `onBeforeConnect` Hook +### `createConnState` -Use `onBeforeConnect` when you need access to actor state for authentication: +Use `createConnState` to extract user data from credentials and store it in connection state. This data is accessible in actions via `c.conn.state`. Like `onBeforeConnect`, throwing an error will reject the connection. See [connections](/docs/actors/connections) for more details. ```typescript -const userProfileActor = actor({ - // Empty onAuth allows all requests to reach the actor - onAuth: () => ({}), - - state: { - ownerId: null as string | null, - isPrivate: false - }, - - onBeforeConnect: async (c, opts) => { - const { params } = opts; - const userId = await validateUser(params.token); - - // Check if user can access this profile - if (c.state.isPrivate && c.state.ownerId !== userId) { - throw new UserError("Access denied to private profile"); +import { actor, UserError } from "rivetkit"; + +interface ConnParams { + authToken: string; +} + +interface ConnState { + userId: string; + role: string; +} + +const chatRoom = actor({ + state: { messages: [] }, + + createConnState: async (c, params: ConnParams): Promise => { + const roomName = c.key; + const payload = await validateToken(params.authToken, roomName); + if (!payload) { + throw new UserError("Forbidden", { code: "forbidden" }); } + return { + userId: payload.sub, + role: payload.role, + }; }, - - createConnState: (c, opts, params: { userId: string }) => { - return { userId: params.userId }; - }, - + actions: { - updateProfile: (c, data) => { - // Check ownership - if (c.state.ownerId !== c.conn.state.userId) { - throw new UserError("Only owner can update profile"); + sendMessage: (c, text: string) => { + // Access user data via c.conn.state + const { userId, role } = c.conn.state; + + if (role !== "member") { + throw new UserError("Insufficient permissions", { code: "insufficient_permissions" }); } - - // Update profile... - } - } + + c.state.messages.push({ userId, text, timestamp: Date.now() }); + c.broadcast("newMessage", { userId, text }); + }, + }, }); ``` - -Prefer `onAuth` over `onBeforeConnect` when possible, as `onAuth` runs on the HTTP server and uses fewer actor resources. - +## Available Auth Data + +Authentication hooks have access to several properties: + +| Property | Description | +|----------|-------------| +| `params` | Custom data passed by the client when connecting (see [connection params](/docs/actors/connections#extracting-data-from-connection-params)) | +| `c.request` | The underlying HTTP request object | +| `c.request.headers` | Request headers for tokens, API keys (does not work for `.connect()`) | +| `c.state` | Actor state for authorization decisions (see [state](/docs/actors/state)) | +| `c.key` | The actor's key (see [keys](/docs/actors/keys)) | + +It's recommended to use `params` instead of `c.request.headers` whenever possible since it works for both HTTP & WebSocket connections. -## Connection Parameters +## Client Usage + +### Passing Credentials Pass authentication data when connecting: -```typescript -// Client side -const chat = client.chatRoom.getOrCreate(["general"]); -const connection = chat.connect({ - authToken: "jwt-token-here", - userId: "user-123" -}); + +```typescript {{"title":"Connection"}} +import { createClient } from "rivetkit/client"; -// Or with action calls -const counter = client.counter.getOrCreate(["user-counter"], { - authToken: "jwt-token-here" +const client = createClient(); +const chat = client.chatRoom.getOrCreate(["general"], { + params: { authToken: "jwt-token-here" }, }); + +// Authentication will happen on connect by reading connection parameters +const connection = chat.connect(); ``` -## Intent-Based Authentication (Experimental) +```typescript {{"title":"Stateless Action"}} +import { createClient } from "rivetkit/client"; -The `onAuth` hook receives an `intents` parameter indicating what the client wants to do: +const client = createClient(); +const chat = client.chatRoom.getOrCreate(["general"], { + params: { authToken: "jwt-token-here" }, +}); -```typescript -const secureActor = actor({ - onAuth: async (params: { token: string }, { intents }) => { - // Different validation based on intent - if (intents.has("action")) { - // Requires higher privileges for actions - return await validateAdminToken(params.token); - } else if (intents.has("connect")) { - // Lower privileges for connections/events - return await validateUserToken(params.token); - } - - throw new UserError("Unknown intent"); +// Authentication will happen when calling the action by reading input +// parameters +await chat.sendMessage("Hello, world!"); +``` + +```typescript {{"title":"HTTP Headers"}} +import { createClient } from "rivetkit/client"; + +// This only works for stateless actions, not WebSockets +const client = createClient({ + headers: { + Authorization: "Bearer my-token", }, - - actions: { - adminAction: (c) => { - // Only accessible with admin token - return "Admin action performed"; - } - } }); -``` -## Error Handling +const chat = client.chatRoom.getOrCreate(["general"]); -### Authentication Errors +// Authentication will happen when calling the action by reading headers +await chat.sendMessage("Hello, world!"); +``` + -Use specific error types for different authentication failures: +### Handling Errors -```typescript -import { UserError, Unauthorized, Forbidden } from "rivetkit/errors"; +Authentication errors use the same system as regular errors. See [errors](/docs/actors/errors) for more details. -const protectedActor = actor({ - onAuth: async (params: { authToken?: string }) => { - const token = params.authToken; - - if (!token) { - throw new Unauthorized("Authentication token required"); - } - - try { - const user = await validateToken(token); - return user; - } catch (error) { - if (error.name === "TokenExpired") { - throw new Unauthorized("Token has expired"); - } - throw new Unauthorized("Invalid authentication token"); - } - }, - - actions: { - adminOnly: (c) => { - if (c.conn.auth.role !== "admin") { - throw new Forbidden("Admin access required"); - } - return "Admin content"; - } + +```typescript {{"title":"Connection"}} +import { ActorError } from "rivetkit/client"; + +const conn = actor.connect(); +conn.onError((error: ActorError) => { + if (error.code === "forbidden") { + window.location.href = "/login"; + } else if (error.code === "insufficient_permissions") { + showError("You don't have permission for this action"); } }); ``` -### Client Error Handling - -Handle authentication errors on the client: +```typescript {{"title":"Stateless Action"}} +import { ActorError } from "rivetkit/client"; -```typescript try { - const result = await protectedActor.adminOnly(); + const result = await actor.protectedAction(); } catch (error) { - if (error.code === "UNAUTHORIZED") { - // Redirect to login + if (error instanceof ActorError && error.code === "forbidden") { window.location.href = "/login"; - } else if (error.code === "FORBIDDEN") { - // Show permission denied message + } else if (error instanceof ActorError && error.code === "insufficient_permissions") { showError("You don't have permission for this action"); } } ``` + -## Integration with Auth Providers - -### Better Auth Integration +## Examples - - - Complete integration guide for Better Auth - - +### JWT -### JWT Authentication +Validate JSON Web Tokens and extract user claims: ```typescript import { actor, UserError } from "rivetkit"; import jwt from "jsonwebtoken"; +interface ConnParams { + token: string; +} + +interface ConnState { + userId: string; + role: string; + permissions: string[]; +} + const jwtActor = actor({ - onAuth: async (params: { jwt?: string }, { request }) => { - const token = params.jwt || - request.headers.get("Authorization")?.replace("Bearer ", ""); - - if (!token) { - throw new UserError("JWT token required"); - } - + state: {}, + + createConnState: (c, params: ConnParams): ConnState => { try { - const payload = jwt.verify(token, process.env.JWT_SECRET!); + const payload = jwt.verify(params.token, process.env.JWT_SECRET!) as any; return { userId: payload.sub, role: payload.role, - permissions: payload.permissions || [] + permissions: payload.permissions || [], }; - } catch (error) { - throw new UserError("Invalid or expired JWT token"); + } catch { + throw new UserError("Invalid or expired token", { code: "invalid_token" }); } }, - + actions: { - protectedAction: (c, data) => { - const { permissions } = c.conn.auth; - - if (!permissions.includes("write")) { - throw new UserError("Write permission required"); + protectedAction: (c) => { + if (!c.conn.state.permissions.includes("write")) { + throw new UserError("Write permission required", { code: "forbidden" }); } - - // Perform action... return { success: true }; - } - } + }, + }, }); ``` -### API Key Authentication +### External Auth Provider + +Validate credentials against an external authentication service: ```typescript +import { actor, UserError } from "rivetkit"; + +interface ConnParams { + apiKey: string; +} + +interface ConnState { + userId: string; + tier: string; +} + const apiActor = actor({ - onAuth: async (params: { apiKey?: string }, { request }) => { - const apiKey = params.apiKey || - request.headers.get("X-API-Key"); - - if (!apiKey) { - throw new UserError("API key required"); - } - - // Validate with your API service - const response = await fetch(`${process.env.AUTH_SERVICE}/validate`, { + state: {}, + + createConnState: async (c, params: ConnParams): Promise => { + const response = await fetch(`https://api.my-auth-provider.com/validate`, { method: "POST", - headers: { "X-API-Key": apiKey } + headers: { "X-API-Key": params.apiKey }, }); - + if (!response.ok) { - throw new UserError("Invalid API key"); + throw new UserError("Invalid API key", { code: "invalid_api_key" }); } - - const user = await response.json(); - return { - userId: user.id, - tier: user.tier, - rateLimit: user.rateLimit - }; + + const data = await response.json(); + return { userId: data.id, tier: data.tier }; }, - + actions: { premiumAction: (c) => { - if (c.conn.auth.tier !== "premium") { - throw new UserError("Premium subscription required"); + if (c.conn.state.tier !== "premium") { + throw new UserError("Premium subscription required", { code: "forbidden" }); } - return "Premium content"; + }, + }, +}); +``` + +### Using `c.state` In Authorization + +Access actor state via `c.state` and the actor's key via `c.key` to make authorization decisions: + +```typescript +import { actor, UserError } from "rivetkit"; + +interface ConnParams { + userId?: string; +} + +const userProfile = actor({ + state: { + ownerId: "user-123", + isPrivate: true, + }, + + onBeforeConnect: (c, params: ConnParams) => { + // Use actor state to check access permissions + if (c.state.isPrivate && params.userId !== c.state.ownerId) { + throw new UserError("Access denied to private profile", { code: "forbidden" }); } - } + }, + + actions: { + getProfile: (c) => ({ ownerId: c.state.ownerId }), + }, }); ``` -## Role-Based Access Control +### Role-Based Access Control -Implement RBAC with helper functions: +Create helper functions for common authorization patterns: ```typescript -// auth-helpers.ts -export function requireRole(requiredRole: string) { - return (c: any) => { - const userRole = c.conn.auth.role; - const roleHierarchy = { "user": 1, "moderator": 2, "admin": 3 }; - - if (roleHierarchy[userRole] < roleHierarchy[requiredRole]) { - throw new UserError(`${requiredRole} role required`); +import { actor, UserError } from "rivetkit"; + +const ROLE_HIERARCHY = { user: 1, moderator: 2, admin: 3 }; + +interface ConnState { + role: keyof typeof ROLE_HIERARCHY; + permissions: string[]; +} + +function requireRole(requiredRole: keyof typeof ROLE_HIERARCHY) { + return (c: { conn: { state: ConnState } }) => { + const userRole = c.conn.state.role; + if (ROLE_HIERARCHY[userRole] < ROLE_HIERARCHY[requiredRole]) { + throw new UserError(`${requiredRole} role required`, { code: "forbidden" }); } }; } -export function requirePermission(permission: string) { - return (c: any) => { - const permissions = c.conn.auth.permissions || []; - if (!permissions.includes(permission)) { - throw new UserError(`Permission '${permission}' required`); +function requirePermission(permission: string) { + return (c: { conn: { state: ConnState } }) => { + if (!c.conn.state.permissions?.includes(permission)) { + throw new UserError(`Permission '${permission}' required`, { code: "forbidden" }); } }; } -// usage in actor const forumActor = actor({ - onAuth: async (params: { token: string }) => { - // ... authenticate and return user with role/permissions + state: {}, + + createConnState: async (c, params: { token: string }): Promise => { + const user = await validateToken(params.token); + return { role: user.role, permissions: user.permissions }; }, - + actions: { deletePost: (c, postId: string) => { requireRole("moderator")(c); - // Delete post logic... + // Delete post... }, - + editPost: (c, postId: string, content: string) => { requirePermission("edit_posts")(c); - // Edit post logic... + // Edit post... + }, + }, +}); +``` + +### Rate Limiting + +Use `c.vars` to track connection attempts and rate limit by user: + +```typescript +import { actor, UserError } from "rivetkit"; + +interface ConnParams { + authToken: string; +} + +interface RateLimitEntry { + count: number; + resetAt: number; +} + +const rateLimitedActor = actor({ + state: {}, + vars: { rateLimits: {} as Record }, + + onBeforeConnect: async (c, params: ConnParams) => { + // Extract user ID + const { userId } = await validateToken(params.authToken); + + // Check rate limit + const now = Date.now(); + const limit = c.vars.rateLimits[userId]; + + if (limit && limit.resetAt > now && limit.count >= 10) { + throw new UserError("Too many requests, try again later", { code: "rate_limited" }); } - } + + // Update rate limit + if (!limit || limit.resetAt <= now) { + c.vars.rateLimits[userId] = { count: 1, resetAt: now + 60_000 }; + } else { + limit.count++; + } + }, + + actions: { + getData: (c) => ({ success: true }), + }, }); ``` -## Testing Authentication +The limits in this example are [ephemeral](/docs/actors/state#ephemeral-variables-vars). If you wish to persist rate limits, you can optionally replace `vars` with `state`. -Mock authentication for testing: +### Caching Tokens + +Cache validated tokens in `c.vars` to avoid redundant validation on repeated connections. See [ephemeral variables](/docs/actors/state#ephemeral-variables-vars) for more details. ```typescript -// test helpers -export function createMockAuth(userData: any) { - return { - onAuth: async () => userData +import { actor, UserError } from "rivetkit"; + +interface ConnParams { + authToken: string; +} + +interface ConnState { + userId: string; + role: string; +} + +interface TokenCache { + [token: string]: { + userId: string; + role: string; + expiresAt: number; }; } -// in tests -describe("Protected Actor", () => { - it("allows admin actions", async () => { - const mockActor = { - ...protectedActor, - ...createMockAuth({ role: "admin", userId: "123" }) - }; - - const result = await mockActor.adminOnly(); - expect(result).toBe("Admin content"); - }); - - it("denies non-admin actions", async () => { - const mockActor = { - ...protectedActor, - ...createMockAuth({ role: "user", userId: "123" }) +const cachedAuthActor = actor({ + state: {}, + vars: { tokenCache: {} as TokenCache }, + + createConnState: async (c, params: ConnParams): Promise => { + const token = params.authToken; + + // Check cache first + const cached = c.vars.tokenCache[token]; + if (cached && cached.expiresAt > Date.now()) { + return { userId: cached.userId, role: cached.role }; + } + + // Validate token (expensive operation) + const payload = await validateToken(token); + if (!payload) { + throw new UserError("Invalid token", { code: "invalid_token" }); + } + + // Cache the result + c.vars.tokenCache[token] = { + userId: payload.sub, + role: payload.role, + expiresAt: Date.now() + 5 * 60 * 1000, // 5 minutes }; - - await expect(mockActor.adminOnly()).rejects.toThrow("Admin access required"); - }); + + return { userId: payload.sub, role: payload.role }; + }, + + actions: { + getData: (c) => ({ userId: c.conn.state.userId }), + }, }); ``` -## Best Practices - -1. **Use onAuth**: Prefer `onAuth` over `onBeforeConnect` for most authentication -2. **Validate Early**: Authenticate at the HTTP server level when possible -3. **Specific Errors**: Use appropriate error types (Unauthorized, Forbidden) -4. **Rate Limiting**: Consider rate limiting in your authentication logic -5. **Token Refresh**: Handle token expiration gracefully on the client -6. **Audit Logging**: Log authentication events for security monitoring -7. **Least Privilege**: Only grant the minimum permissions needed diff --git a/website/src/content/docs/actors/clients.mdx b/website/src/content/docs/actors/clients.mdx index 5abfc8f030..4345e2fbcc 100644 --- a/website/src/content/docs/actors/clients.mdx +++ b/website/src/content/docs/actors/clients.mdx @@ -1,596 +1,466 @@ -import imgActorActorClient from "./images/actor-actor-client.png"; -import imgExtrnalClient from "./images/external-client.png"; -import imgServerSideClient from "./images/server-side-client.png"; +# Clients -# Actor Clients +Clients are used to get and communicate with actors from your application. Clients can be created from either your frontend or backend. -Learn how to call actions and connect to actors from client applications using Rivet's TypeScript client library. - -Rivet also supports [React](/docs/clients/react) and [Rust](/docs/clients/rust) clients. - -Using the RivetKit client is completely optional. If you prefer to write your own networking logic, you can either: - -- Write your own HTTP endpoints and use the client returned from `registry.start` (see below) -- Make HTTP requests directly to the registry (see [OpenAPI spec](/docs/clients/openapi)) - -## Client Setup - -There are several ways to create a client for communicating with actors: +## Creating a Client - - Server-side client diagram - - From your backend server that hosts the registry: - - ```typescript {{"title":"server.ts"}} - import { registry } from "./registry"; - import { Hono } from "hono"; - import { serve } from "@hono/node-server"; - - const { client } = registry.start(); - - const app = new Hono(); - - app.post("/foo", () => { - const response = await client.myActor.getOrCreate("my-id").bar(); - return c.json(response); - }); + + For frontend applications or external services: - serve(app); - ``` - - This client doesn't [require authentication](/docs/actors/authentication). - - - - External client diagram - - For frontend applications or external services connecting to your Rivet backend: - - ```typescript {{"title":"client.ts"}} + + ```typescript {{"title":"JavaScript"}} import { createClient } from "rivetkit/client"; - import type { registry } from "./registry"; // IMPORTANT: Must use `type` - - const client = createClient("http://localhost:8080"); + import type { registry } from "./registry"; // Must use `type` - const response = await client.otherActor.getOrCreate().foo(); + const client = createClient(); ``` - Configure the client with additional options: + ```tsx {{"title":"React"}} + import { createRivetKit } from "@rivetkit/react"; + import type { registry } from "./registry"; // Must use `type` - ```typescript {{"tilte":"client.ts"}} - const client = createClient("http://localhost:8080", { - // Data serialization format - encoding: "cbor", // or "json" - - // Network transport - transport: "websocket", // or "sse" - }); + const { useActor } = createRivetKit(); ``` + + + + Clients include the following options: + + ```typescript + const client = createClient({ + endpoint: "https://api.rivet.dev", + namespace: "default", + token: "my-token", + encoding: "json", // "json", "cbor", or "bare" + headers: { "X-Custom-Header": "value" } + }); + ``` + + - This client [requires authentication](/docs/actors/authentication). - - **Important**: Use `import type` when importing the registry type in order to - avoid accidentally bundling your backend code. + + From your backend server that hosts the registry: - ```typescript {{"title":"client.ts"}} - // ✅ Do this - import type { registry } from "./registry" + ```typescript + import { registry } from "./registry"; - // 🚫 Not this - import { registry } from "./registry" + const { client } = registry.start(); ``` - - Actor-to-actor client diagram - + From within an actor to communicate with other actors: - ```typescript {{"title":"actor.ts"}} + ```typescript const myActor = actor({ actions: { callOtherActor: (c) => { const client = c.client(); - return await client.otherActor.getOrCreate("my-id").foo(); + // ... } } }); ``` - This client doesn't [require authentication](/docs/actors/authentication). - Read more about [communicating between actors](/docs/actors/communicating-between-actors). -## `ActorClient` +## Getting an Actor -The `ActorClient` provides methods for finding and creating actors. All methods return an `ActorHandle` that you can use to call actions or establish connections. +### `getOrCreate` -### `get(key?, opts?)` - Find Existing Actor +Returns a handle to an existing actor or creates one if it doesn't exist: -Returns a handle to an existing actor or `null` if it doesn't exist: + +```typescript {{"title":"JavaScript"}} +const counter = client.counter.getOrCreate("my-counter"); +const count = await counter.increment(5); +``` -```typescript -// Get existing actor by key -const handle = client.myActor.get(["actor-id"]); +```tsx {{"title":"React"}} +const counter = useActor({ + name: "counter", + key: ["my-counter"], +}); -if (handle) { - const result = await handle.someAction(); -} else { - console.log("Actor doesn't exist"); -} +// Call actions through the connection +await counter.connection?.increment(5); ``` + -### `getOrCreate(key?, opts?)` - Find or Create Actor - -Returns a handle to an existing actor or creates a new one if it doesn't exist: +Pass initialization data when creating: -```typescript -// Get or create actor (synchronous) -const counter = client.counter.getOrCreate(["my-counter"]); - -// With initialization input -const game = client.game.getOrCreate(["game-123"], { - createWithInput: { - gameMode: "tournament", - maxPlayers: 8, - } + +```typescript {{"title":"JavaScript"}} +const game = client.game.getOrCreate("game-123", { + createWithInput: { gameMode: "tournament", maxPlayers: 8 } }); - -// Call actions immediately -const count = await counter.increment(5); ``` - -`get()` and `getOrCreate()` are synchronous and return immediately. The actor is created lazily when you first call an action. - +```tsx {{"title":"React"}} +const game = useActor({ + name: "game", + key: ["game-123"], + createWithInput: { gameMode: "tournament", maxPlayers: 8 }, +}); +``` + -### `create(key?, opts?)` - Create New Actor +### `get` -Explicitly creates a new actor instance, failing if one already exists: +Returns a handle to an existing actor or `null` if it doesn't exist: -```typescript -// Create new actor (async) -const newGame = await client.game.create(["game-456"], { - input: { - gameMode: "classic", - maxPlayers: 4, - } -}); + +```typescript {{"title":"JavaScript"}} +const handle = client.myActor.get("actor-id"); -// Actor is guaranteed to be newly created -await newGame.initialize(); +if (handle) { + await handle.someAction(); +} ``` -### `getForId(id, opts?)` - Find by Internal ID +```tsx {{"title":"React"}} +import { createClient } from "rivetkit/client"; +import { useMemo } from "react"; +import type { registry } from "./registry"; -Connect to an actor using its internal system ID: +// `get` is not currently supported with useActor. +// Use createClient with useMemo instead: -```typescript -// Connect by internal ID -const actorId = "55425f42-82f8-451f-82c1-6227c83c9372"; -const actor = client.myActor.getForId(actorId); +function MyComponent() { + const client = useMemo(() => createClient(), []); + const handle = useMemo(() => client.myActor.get("actor-id"), [client]); -await actor.performAction(); + // Use handle to call actions +} ``` + - -Prefer using keys over internal IDs for actor discovery. IDs are primarily for debugging and advanced use cases. - +### `create` -## `ActorHandle` +Creates a new actor, failing if one already exists with that key: -An `ActorHandle` represents a reference to an actor instance and provides methods for calling actions and establishing connections. You get an `ActorHandle` from the `ActorClient` methods like `get()`, `getOrCreate()`, and `create()`. + +```typescript {{"title":"JavaScript"}} +const newGame = await client.game.create("game-456", { + input: { gameMode: "classic" } +}); +``` -### Calling Actions +```tsx {{"title":"React"}} +import { createClient } from "rivetkit/client"; +import { useMemo, useEffect, useState } from "react"; +import type { registry } from "./registry"; -You can call actions directly on an `ActorHandle`: +// `create` is not currently supported with useActor. +// Use createClient with useMemo instead: -```typescript -const counter = client.counter.getOrCreate(["my-counter"]); +function MyComponent() { + const client = useMemo(() => createClient(), []); + const [handle, setHandle] = useState(null); -// Call actions directly -const count = await counter.increment(5); -const currentValue = await counter.getCount(); -await counter.reset(); + useEffect(() => { + client.game.create("game-456", { + input: { gameMode: "classic" } + }).then(setHandle); + }, [client]); + + // Use handle to call actions +} ``` + -Actions called on an `ActorHandle` are stateless - each call is independent and doesn't maintain a persistent connection to the actor. +### `getForId` -### `fetch(input, init?)` - Raw HTTP Requests +Connect to an actor using its internal ID: -Make direct HTTP requests to the actor's `onFetch` handler: + +```typescript {{"title":"JavaScript"}} +const actor = client.myActor.getForId("lrysjam017rhxofttna2x5nzjml610"); +``` -```typescript -const actor = client.myActor.getOrCreate(["key"]); +```tsx {{"title":"React"}} +import { createClient } from "rivetkit/client"; +import { useMemo } from "react"; +import type { registry } from "./registry"; -// GET request -const response = await actor.fetch("/api/hello", { - method: "GET" -}); -const data = await response.json(); +// `getForId` is not currently supported with useActor. +// Use createClient with useMemo instead: -// POST request with body -const postResponse = await actor.fetch("/api/echo", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ message: "Hello world" }) -}); +function MyComponent({ actorId }: { actorId: string }) { + const client = useMemo(() => createClient(), []); + const handle = useMemo(() => client.myActor.getForId(actorId), [client, actorId]); -// Can also pass a Request object -const request = new Request("/api/data", { method: "GET" }); -const requestResponse = await actor.fetch(request); + // Use handle to call actions +} ``` + -See [Fetch & WebSocket Handler](/docs/actors/fetch-and-websocket-handler) documentation for more information. - - -For most use cases, actions provide a higher-level API that's easier to work with than raw HTTP handlers. - +Prefer using keys over internal IDs for simplicity. -### `websocket(path?, protocols?)` - Raw WebSocket Connections +## Calling Actions -Create direct WebSocket connections to the actor's `onWebSocket` handler: + +```typescript {{"title":"JavaScript"}} +const counter = client.counter.getOrCreate("my-counter"); -```typescript -const actor = client.myActor.getOrCreate(["key"]); +const count = await counter.increment(5); +const value = await counter.getCount(); +await counter.reset(); +``` -// Basic WebSocket connection -const ws = await actor.websocket(); -ws.addEventListener("message", (event) => { - console.log("Message:", event.data); +```tsx {{"title":"React"}} +const counter = useActor({ + name: "counter", + key: ["my-counter"], }); -ws.send("Hello WebSocket!"); -// WebSocket with custom path -const streamWs = await actor.websocket("/stream"); - -// WebSocket with protocols -const protocolWs = await actor.websocket("/", ["chat", "v1"]); +// Call actions through the connection +const count = await counter.connection?.increment(5); +const value = await counter.connection?.getCount(); +await counter.connection?.reset(); ``` + -See [Fetch & WebSocket Handler](/docs/actors/fetch-and-websocket-handler) documentation for more information. +In JavaScript, actions called without `connect()` are stateless. Each call is independent without a persistent connection. In React, `useActor` automatically manages a persistent connection. - -For most use cases, actions & events provide a higher-level API that's easier to work with than raw HTTP handlers. - - -### `connect(params?)` - Establish Stateful Connection +## Connecting to an Actor -To open a stateful connection using `ActorConn`, call `.connect()`: +For real-time use cases, establish a persistent connection to the actor: -```typescript -const counter = client.counter.getOrCreate(["live-counter"]); -const connection = counter.connect(); + +```typescript {{"title":"JavaScript"}} +const counter = client.counter.getOrCreate("live-counter"); +const conn = counter.connect(); // Listen for events -connection.on("countChanged", (newCount: number) => { +conn.on("countChanged", (newCount: number) => { console.log("Count updated:", newCount); }); // Call actions through the connection -const result = await connection.increment(1); +await conn.increment(1); +``` + +```tsx {{"title":"React"}} +const [count, setCount] = useState(0); + +const counter = useActor({ + name: "counter", + key: ["live-counter"], +}); -// Clean up when done -await connection.dispose(); +// Listen for events +counter.useEvent("countChanged", (newCount: number) => { + setCount(newCount); +}); + +// Call actions through the connection +await counter.connection?.increment(1); ``` + -## `ActorConn` +## Subscribing to Events -Real-time connections enable bidirectional communication between clients and actors through persistent connections. Rivet automatically negotiates between WebSocket (preferred for full duplex) and Server-Sent Events (SSE) as a fallback for restrictive environments. +Listen for events from connected actors: -For more information on connections, see the [connections documentation](/docs/actors/connections). For more information on handling events, see the [events documentation](/docs/actors/events). + +```typescript {{"title":"JavaScript"}} +const conn = client.chatRoom.getOrCreate("general").connect(); -### Calling Actions +// Listen for events +conn.on("messageReceived", (message) => { + console.log(`${message.from}: ${message.text}`); +}); -You can also call actions through an `ActorConn`, just like with an `ActorHandle`: +// Listen once +conn.once("gameStarted", () => { + console.log("Game has started!"); +}); +``` -```typescript -const connection = counter.connect(); +```tsx {{"title":"React"}} +const [messages, setMessages] = useState([]); -// Call actions through the connection -const count = await connection.increment(5); -const currentValue = await connection.getCount(); +const chatRoom = useActor({ + name: "chatRoom", + key: ["general"], +}); + +// Listen for events (automatically cleaned up on unmount) +chatRoom.useEvent("messageReceived", (message) => { + setMessages((prev) => [...prev, message]); +}); ``` + -### Reconnections +## Full-Stack Type Safety -Connections automatically handle network failures with built-in reconnection logic: +Import types from your registry for end-to-end type safety: -- **Exponential backoff**: Retry delays increase progressively to avoid overwhelming the server -- **Action queuing**: Actions called while disconnected are queued and sent once reconnected -- **Event resubscription**: Event listeners are automatically restored on reconnection + +```typescript {{"title":"JavaScript"}} +import { createClient } from "rivetkit/client"; +import type { registry } from "./registry"; -### `on(eventName, callback)` - Listen for Events +const client = createClient(); -Listen for events from the actor: +// IDE autocomplete shows available actors and actions +const counter = client.counter.getOrCreate("my-counter"); +const count = await counter.increment(5); +``` -```typescript -// Listen for chat messages -connection.on("messageReceived", (message) => { - console.log(`${message.from}: ${message.text}`); -}); +```tsx {{"title":"React"}} +import { createRivetKit } from "@rivetkit/react"; +import type { registry } from "./registry"; -// Listen for game state updates -connection.on("gameStateChanged", (gameState) => { - updateUI(gameState); -}); +const { useActor } = createRivetKit(); -// Listen for player events -connection.on("playerJoined", (player) => { - console.log(`${player.name} joined the game`); -}); +// IDE autocomplete shows available actors and actions +const counter = useActor({ name: "counter", key: ["my-counter"] }); +const count = await counter.connection?.increment(5); ``` + + + +Use `import type` to avoid accidentally bundling backend code in your frontend. + -### `once(eventName, callback)` - Listen Once +## Advanced -Listen for an event only once: +### Disposing Clients & Connections + +Dispose clients to close all connections: ```typescript -// Wait for game to start -connection.once("gameStarted", () => { - console.log("Game has started!"); -}); +await client.dispose(); ``` -### `dispose()` - Clean Up Connection - -Always dispose of connections when finished to free up resources: +Dispose individual connections when finished: ```typescript -const connection = actor.connect(); +const conn = actor.connect(); try { - // Use the connection - connection.on("event", handler); - await connection.someAction(); + conn.on("event", handler); + await conn.action(); } finally { - // Clean up the connection - await connection.dispose(); + await conn.dispose(); } - -// Or with automatic cleanup in React/frameworks -useEffect(() => { - const connection = actor.connect(); - - return () => { - connection.dispose(); - }; -}, []); ``` -**Important:** Disposing a connection: -- Closes the underlying WebSocket or SSE connection -- Removes all event listeners -- Cancels any pending reconnection attempts -- Prevents memory leaks in long-running applications - -## Authentication + +When using `useActor` in React, connections are automatically disposed when the component unmounts. No manual cleanup is required. + ### Connection Parameters -Pass authentication data when connecting to actors: +Pass custom data to the actor when connecting: -```typescript -// With connection parameters -const chat = client.chatRoom.getOrCreate(["general"], { + +```typescript {{"title":"JavaScript"}} +const chat = client.chatRoom.getOrCreate("general", { params: { - authToken: "jwt-token-here", userId: "user-123", displayName: "Alice" } }); - -const connection = chat.connect(); - -// Or for action calls -const result = await chat.sendMessage("Hello world!"); ``` -### onAuth Hook Validation - -Actors can validate authentication using the `onAuth` hook: - -```typescript -import { actor, UserError } from "rivetkit"; - -const protectedActor = actor({ - onAuth: async (opts) => { - const { req, params, intents } = opts; - - // Extract token from params or headers - const token = params.authToken || req.headers.get("Authorization"); - - if (!token) { - throw new UserError("Authentication required", { code: "missing_auth" }); - } - - // Validate and return user data - const user = await validateJWT(token); - - // Check permissions based on what the client is trying to do - if (intents.has("create") && user.role !== "admin") { - throw new UserError("Admin access required", { code: "insufficient_permissions" }); - } - - return { userId: user.id, role: user.role }; +```tsx {{"title":"React"}} +const chat = useActor({ + name: "chatRoom", + key: ["general"], + params: { + userId: "user-123", + displayName: "Alice" }, - - actions: { - protectedAction: (c, data: string) => { - // Access auth data via c.conn.auth - const { userId, role } = c.conn.auth; - - if (role !== "admin") { - throw new UserError("Admin access required", { code: "insufficient_permissions" }); - } - - return `Hello admin ${userId}`; - } - } }); ``` + -Learn more about [authentication patterns](/docs/actors/authentication). - -## Type Safety - -Rivet provides end-to-end type safety between clients and actors: - -### Action Type Safety - -TypeScript validates action signatures and return types: - -```typescript -// TypeScript knows the action signatures -const counter = client.counter.getOrCreate(["my-counter"]); +### Authentication -const count: number = await counter.increment(5); // ✓ Correct -const invalid = await counter.increment("5"); // ✗ Type error +Pass authentication tokens when connecting: -// IDE autocomplete shows available actions -counter./* */ + +```typescript {{"title":"JavaScript"}} +const chat = client.chatRoom.getOrCreate("general", { + params: { + authToken: "jwt-token-here" + } +}); ``` -### Client Type Safety - -Import types from your registry for full type safety: - -```typescript -import type { registry } from "./registry"; - -// Client is fully typed -const client = createClient("http://localhost:8080"); - -// IDE provides autocomplete for all actors -client./* */ +```tsx {{"title":"React"}} +const chat = useActor({ + name: "chatRoom", + key: ["general"], + params: { + authToken: "jwt-token-here" + }, +}); ``` + -## Best Practices - -### `ActorHandle` (Stateless) vs `ActorConn` (Stateful) Clients - -**Use `ActorHandle` (Stateless) For:** -- Simple request-response operations -- One-off operations -- Server-side integration +See [authentication](/docs/actors/authentication) for more details. -```typescript -// Good for simple operations -const result = await counter.increment(1); -const status = await server.getStatus(); -``` +### Error Handling -**Use `ActorConn` (Stateful) Connections For:** -- Real-time updates needed -- Event-driven interactions -- Long-lived client sessions + +```typescript {{"title":"JavaScript (Connection)"}} +import { ActorError } from "rivetkit/client"; -```typescript -// Good for real-time features -const connection = chatRoom.connect(); -connection.on("messageReceived", updateUI); -await connection.sendMessage("Hello!"); +const conn = actor.connect(); +conn.onError((error: ActorError) => { + if (error.code === "forbidden") { + window.location.href = "/login"; + } +}); ``` -### Resource Management +```typescript {{"title":"JavaScript (Stateless)"}} +import { ActorError } from "rivetkit/client"; -Always clean up connections when finished: - -```typescript -// Manual cleanup -const connection = actor.connect(); try { - // Use connection - connection.on("event", handler); - await connection.action(); -} finally { - await connection.dispose(); + const result = await actor.protectedAction(); +} catch (error) { + if (error instanceof ActorError && error.code === "forbidden") { + window.location.href = "/login"; + } } ``` -### Error Handling +```tsx {{"title":"React"}} +import { ActorError } from "rivetkit/client"; -Handle connection errors using the `.onError()` method: +const actor = useActor({ name: "myActor", key: ["id"] }); - - -```typescript {{"title":"TypeScript"}} -const connection = actor.connect(); - -connection.onError((error) => { - console.error('Connection error:', error); - showErrorMessage(error.message); - - // Handle specific error types - if (error.code === 'UNAUTHORIZED') { - redirectToLogin(); - } else if (error.code === 'ACTOR_NOT_FOUND') { - showActorNotFoundError(); +const handleAction = async () => { + try { + await actor.connection?.protectedAction(); + } catch (error) { + if (error instanceof ActorError && error.code === "forbidden") { + window.location.href = "/login"; + } } -}); +}; ``` + -```tsx {{"title":"React"}} -import { useState, useEffect } from "react"; -import { useActor } from "./rivetkit"; - -function ConnectionErrorHandler() { - const [connectionError, setConnectionError] = useState(null); - const [errorCode, setErrorCode] = useState(null); - - const actor = useActor({ - name: "chatRoom", - key: ["general"] - }); - - useEffect(() => { - if (!actor.connection) return; - - const unsubscribe = actor.connection.onError((error) => { - console.error('Connection error:', error); - setConnectionError(error.message); - setErrorCode(error.code); - - // Clear error after 5 seconds - setTimeout(() => { - setConnectionError(null); - setErrorCode(null); - }, 5000); - }); - - // Clean up error handler when component unmounts - return unsubscribe; - }, [actor.connection]); - - // ...rest of component... -} -``` +See [errors](/docs/actors/errors) for more details. - +### Actor Resolution -### Execute Actions in Parallel +`get` and `getOrCreate` return immediately without making a network request. The actor is resolved lazily when you call an action or `connect()`. -You can execute batch requests in parallel: +To explicitly resolve an actor and get its ID, use `resolve()`: ```typescript -// Batch multiple operations through a connection -const connection = actor.connect(); -await Promise.all([ - connection.operation1(), - connection.operation2(), - connection.operation3(), -]); - -// Use getOrCreate for actors you expect to exist -const existing = client.counter.getOrCreate(["known-counter"]); - -// Use create only when you need a fresh instance -const fresh = await client.counter.create(["new-counter"]); +const handle = client.counter.getOrCreate("my-counter"); +const actorId = await handle.resolve(); +console.log(actorId); // "lrysjam017rhxofttna2x5nzjml610" ``` -However, it's recommended to move this logic to run within the actor instead of the client if executing multiple actions is a common pattern. - diff --git a/website/src/content/docs/actors/communicating-between-actors.mdx b/website/src/content/docs/actors/communicating-between-actors.mdx index e98b2b8b65..97bb4893e2 100644 --- a/website/src/content/docs/actors/communicating-between-actors.mdx +++ b/website/src/content/docs/actors/communicating-between-actors.mdx @@ -23,11 +23,11 @@ const orderProcessor = actor({ const client = c.client(); // Reserve the stock - const inventory = client.inventory.getOrCreate(["main"]); + const inventory = client.inventory.getOrCreate("main"); await inventory.reserveStock(order.quantity); - + // Process payment through payment actor - const payment = client.payment.getOrCreate([order.customerId]); + const payment = client.payment.getOrCreate(order.customerId); const result = await payment.processPayment(order.amount); // Update order state @@ -56,15 +56,15 @@ const workflowActor = actor({ const client = c.client(); // Step 1: Initialize data - const dataProcessor = client.dataProcessor.getOrCreate(["main"]); + const dataProcessor = client.dataProcessor.getOrCreate("main"); const data = await dataProcessor.initialize(workflowId); - + // Step 2: Process through multiple actors - const validator = client.validator.getOrCreate(["main"]); + const validator = client.validator.getOrCreate("main"); const validationResult = await validator.validate(data); - + // Step 3: Finalize - const finalizer = client.finalizer.getOrCreate(["main"]); + const finalizer = client.finalizer.getOrCreate("main"); const result = await finalizer.finalize(validationResult); c.state.workflows.push({ workflowId, result, completedAt: Date.now() }); @@ -89,9 +89,9 @@ const analyticsActor = actor({ const client = c.client(); // Collect data from multiple sources - const userMetrics = client.userMetrics.getOrCreate(["main"]); - const orderMetrics = client.orderMetrics.getOrCreate(["main"]); - const systemMetrics = client.systemMetrics.getOrCreate(["main"]); + const userMetrics = client.userMetrics.getOrCreate("main"); + const orderMetrics = client.orderMetrics.getOrCreate("main"); + const systemMetrics = client.systemMetrics.getOrCreate("main"); const [users, orders, system] = await Promise.all([ userMetrics.getStats(), @@ -128,8 +128,8 @@ const auditLogActor = actor({ const client = c.client(); // Connect to multiple actors to listen for events - const userActor = client.userActor.getOrCreate(["main"]).connect(); - const orderActor = client.orderActor.getOrCreate(["main"]).connect(); + const userActor = client.userActor.getOrCreate("main").connect(); + const orderActor = client.orderActor.getOrCreate("main").connect(); // Listen for user events userActor.on("userCreated", (user) => { @@ -162,7 +162,7 @@ Process multiple items in parallel: ```typescript // Process items in parallel const results = await Promise.all( - items.map(item => client.processor.getOrCreate([item.type]).process(item)) + items.map(item => client.processor.getOrCreate(item.type).process(item)) ); ``` diff --git a/website/src/content/docs/actors/connections.mdx b/website/src/content/docs/actors/connections.mdx index 682213a59c..ec1d43ba52 100644 --- a/website/src/content/docs/actors/connections.mdx +++ b/website/src/content/docs/actors/connections.mdx @@ -2,6 +2,8 @@ Connections represent client connections to your actor. They provide a way to handle client authentication, manage connection-specific data, and control the connection lifecycle. +For documentation on connecting to actors from clients, see the [Clients documentation](/docs/actors/clients). + ## Parameters When clients connect to an actor, they can pass connection parameters that are handled during the connection process. @@ -10,7 +12,7 @@ For example: -```typescript {{"title":"client.ts"}} +```typescript {{"title":"Client"}} import { createClient } from "rivetkit/client"; import type { registry } from "./src/index"; @@ -20,21 +22,30 @@ const gameRoom = await client.gameRoom.get({ }); ``` -```typescript {{"title":"actor.ts"}} +```typescript {{"title":"Actor"}} import { actor } from "rivetkit"; +interface ConnParams { + authToken: string; +} + +interface ConnState { + userId: string; + role: string; +} + const gameRoom = actor({ state: {}, - + // Handle connection setup - createConnState: (c, opts, params: { authToken: string }) => { + createConnState: (c, opts, params: ConnParams): ConnState => { // Validate authentication token const authToken = params.authToken; - + if (!authToken || !validateToken(authToken)) { throw new Error("Invalid auth token"); } - + // Create connection state return { userId: getUserIdFromToken(authToken), role: "player" }; }, @@ -53,7 +64,7 @@ const gameRoom = actor({ There are two ways to define an actor's connection state: - + Define connection state as a constant value: ```typescript @@ -61,18 +72,18 @@ There are two ways to define an actor's connection state: const chatRoom = actor({ state: { messages: [] }, - + // Define default connection state as a constant connState: { role: "guest", joinedAt: 0 }, - + onConnect: (c) => { // Update join timestamp when a client connects c.conn.state.joinedAt = Date.now(); }, - + actions: { // ... } @@ -82,28 +93,34 @@ There are two ways to define an actor's connection state: This value will be cloned for every new connection using `structuredClone`. - + Create connection state dynamically with a function called for each connection: ```typescript import { actor } from "rivetkit"; + interface ConnState { + userId: string; + role: string; + joinedAt: number; + } + const chatRoom = actor({ state: { messages: [] }, - + // Create connection state dynamically - createConnState: (c) => { + createConnState: (c): ConnState => { // Validate any connection parameters // ... - + // Return the connection state - return { + return { userId: generateUserId(), role: "guest", joinedAt: Date.now() }; }, - + actions: { sendMessage: (c, message) => { const username = c.conn.state.userId; @@ -122,6 +139,7 @@ The connection lifecycle has several hooks: - `onBeforeConnect`: Called before a client connects, returns the connection state - `onConnect`: Called when a client successfully connects +- `createState`: Called when creating a connection state - `onDisconnect`: Called when a client disconnects See the documentation on [Actor Lifecycle](/docs/actors/lifecycle) for more details. @@ -130,7 +148,7 @@ See the documentation on [Actor Lifecycle](/docs/actors/lifecycle) for more deta All active connections can be accessed through the context object's `conns` property. This is an array of all current connections. -This is frequently used with `conn.send(name, event)` to send messages directly to clients. +This is frequently used with `conn.send(name, event)` to send messages directly to clients. To send an event to all connections at once, use `c.broadcast()` instead. See [Events](/docs/actors/events) for more details on broadcasting. For example: @@ -147,7 +165,7 @@ const chatRoom = actor({ if (recipientConn) { // Send a private message to just that client - recipientConn.send('directMessage', { + recipientConn.send("directMessage", { from: c.conn.state.userId, message: message }); @@ -157,6 +175,10 @@ const chatRoom = actor({ }); ``` + +`conn.send()` has no effect on [low-level WebSocket connections](/docs/actors/websocket-handler). For low-level WebSockets, use the WebSocket API directly (e.g., `websocket.send()`). + + ## Disconnecting clients Connections can be disconnected from within an action: @@ -184,71 +206,7 @@ const secureRoom = actor({ If you need to wait for the disconnection to complete, you can use `await`: ```typescript -await c.conn.disconnect('Too many requests'); +await c.conn.disconnect("Too many requests"); ``` This ensures the underlying network connections close cleanly before continuing. - -## Connection Error Handling - -Handle connection errors using the `.onError()` method: - - - -```typescript {{"title":"TypeScript"}} -const connection = actor.connect(); - -connection.onError((error) => { - console.error('Connection error:', error); - showErrorMessage(error.message); - - // Handle specific error types - if (error.code === 'UNAUTHORIZED') { - redirectToLogin(); - } else if (error.code === 'ACTOR_NOT_FOUND') { - showActorNotFoundError(); - } -}); -``` - -```tsx {{"title":"React"}} -import { useState, useEffect } from "react"; -import { useActor } from "./rivetkit"; - -function ConnectionErrorHandler() { - const [connectionError, setConnectionError] = useState(null); - const [errorCode, setErrorCode] = useState(null); - - const actor = useActor({ - name: "chatRoom", - key: ["general"] - }); - - useEffect(() => { - if (!actor.connection) return; - - const unsubscribe = actor.connection.onError((error) => { - console.error('Connection error:', error); - setConnectionError(error.message); - setErrorCode(error.code); - - // Clear error after 5 seconds - setTimeout(() => { - setConnectionError(null); - setErrorCode(null); - }, 5000); - }); - - // Clean up error handler when component unmounts - return unsubscribe; - }, [actor.connection]); - - // ...rest of component... -} -``` - - - -## Offline & Auto-Reconnection - -See [client documentation](/docs/actors/communicating-between-actors) for details on reconnection behavior. diff --git a/website/src/content/docs/actors/design-patterns.mdx b/website/src/content/docs/actors/design-patterns.mdx new file mode 100644 index 0000000000..59404ba425 --- /dev/null +++ b/website/src/content/docs/actors/design-patterns.mdx @@ -0,0 +1,333 @@ +# Design Patterns + +Common patterns and anti-patterns for building scalable actor systems. + +## How Actors Scale + +Actors are inherently scalable because of how they're designed: + +- **Isolated state:** Each actor manages its own private data. No shared state means no conflicts and no locks, so actors run concurrently without coordination. +- **Actor-to-actor communication:** Actors interact through [actions](/docs/actors/actions) and [events](/docs/actors/events), so they don't need to coordinate access to shared data. This makes it easy to distribute them across machines. +- **Small, focused units:** Each actor handles a limited scope (a single user, document, or chat room), so load naturally spreads across many actors rather than concentrating in one place. +- **Horizontal scaling:** Adding more machines automatically distributes actors across them. + +These properties form the foundation for the patterns described below. + +## Actor Per Entity + +The core pattern is creating one actor per entity in your system. Each actor represents a single user, document, chat room, or other distinct object. This keeps actors small, independent, and easy to scale. + +**Good examples** + +- `User`: Manages user profile, preferences, and authentication +- `Document`: Handles document content, metadata, and versioning +- `ChatRoom`: Manages participants and message history + +**Bad examples** + +- `Application`: Too broad, handles everything +- `DocumentWordCount`: Too granular, should be part of Document actor + +## Coordinator & Data Actors + +Actors scale by splitting state into isolated entities. However, it's common to need to track and coordinate actors in a central place. This is where coordinator actors come in. + +**Data actors** handle the main logic in your application. Examples: chat rooms, user sessions, game lobbies. + +**Coordinator actors** track other actors. Think of them as an index of data actors. Examples: a list of chat rooms, a list of active users, a list of game lobbies. + +**Example: Chat Rooms** + + + + +```ts +import { actor } from "rivetkit"; + +// Data actor: handles messages and connections +const chatRoom = actor({ + state: { messages: [] as { sender: string; text: string }[] }, + actions: { + sendMessage: (c, sender: string, text: string) => { + const message = { sender, text }; + c.state.messages.push(message); + c.broadcast("newMessage", message); + return message; + }, + getHistory: (c) => c.state.messages, + }, +}); + +// Coordinator: indexes chat rooms +const chatRoomList = actor({ + state: { chatRoomIds: [] as string[] }, + actions: { + createChatRoom: async (c, name: string) => { + const client = c.client(); + // Create the chat room actor and get its ID + const handle = await client.chatRoom.create(name); + const actorId = await handle.resolve(); + // Track it in the list + c.state.chatRoomIds.push(actorId); + return actorId; + }, + listChatRooms: (c) => c.state.chatRoomIds, + }, +}); +``` + + + + +```ts +const client = createClient("http://localhost:8080"); + +// Create a new chat room via coordinator +const coordinator = client.chatRoomList.getOrCreate("main"); +const actorId = await coordinator.createChatRoom("general"); + +// Get list of all chat rooms +const chatRoomIds = await coordinator.listChatRooms(); + +// Connect to a chat room using its ID +const chatRoom = client.chatRoom.getForId(actorId); +await chatRoom.sendMessage("alice", "Hello!"); +const history = await chatRoom.getHistory(); +``` + + + + +## Sharding + +Sharding splits a single actor's workload across multiple actors based on a key. Use this when one actor can't handle all the load or data for an entity. + +**How it works:** +- Partition data using a shard key (user ID, region, time bucket, or random) +- Requests are routed to shards based on the key +- Shards operate independently without coordination + +**Example: Sharded Analytics** + +Instead of one analytics actor handling all events, shard by time bucket: + + + + +```ts +const hourlyAnalytics = actor({ + state: { events: [] as Event[] }, + actions: { + trackEvent: (c, event: Event) => { + c.state.events.push(event); + }, + getEvents: (c) => c.state.events, + }, +}); +``` + + + + +```ts +// Shard by hour: hourlyAnalytics:2024-01-15T00, hourlyAnalytics:2024-01-15T01 +const shardKey = new Date().toISOString().slice(0, 13); // "2024-01-15T00" +const analytics = client.hourlyAnalytics.getOrCreate(shardKey); +await analytics.trackEvent({ type: "page_view", url: "/home" }); +``` + + + + +**Example: Sharded Rate Limiter** + +Instead of one rate limiter that becomes a bottleneck, shard randomly: + + + + +```ts +const rateLimiter = actor({ + state: { requests: {} as Record }, + actions: { + checkLimit: (c, userId: string, limit: number) => { + const count = c.state.requests[userId] ?? 0; + if (count >= limit) return false; + c.state.requests[userId] = count + 1; + return true; + }, + }, +}); +``` + + + + +```ts +// Shard randomly: rateLimiter:shard-0, rateLimiter:shard-1, rateLimiter:shard-2 +const shardKey = `shard-${Math.floor(Math.random() * 3)}`; +const limiter = client.rateLimiter.getOrCreate(shardKey); +const allowed = await limiter.checkLimit("user-123", 100); +``` + + + + +Choose shard keys that distribute load evenly. Note that cross-shard queries require coordination. + +## Fan-In & Fan-Out + +Fan-in and fan-out are patterns for distributing work and aggregating results. + +**Fan-Out**: One actor spawns work across multiple actors. Use for parallel processing or broadcasting updates. + +**Fan-In**: Multiple actors send results to one aggregator. Use for collecting results or reducing data. + +**Example: Map-Reduce** + + + + +```ts +// Coordinator fans out tasks, then fans in results +const coordinator = actor({ + state: { results: [] as Result[] }, + actions: { + // Fan-out: distribute work in parallel + startJob: async (c, tasks: Task[]) => { + const client = c.client(); + await Promise.all( + tasks.map(task => client.worker.getOrCreate(task.id).process(task)) + ); + }, + // Fan-in: collect results + reportResult: (c, result: Result) => { + c.state.results.push(result); + }, + getResults: (c) => c.state.results, + }, +}); + +const worker = actor({ + state: {}, + actions: { + process: async (c, task: Task) => { + const result = await doWork(task); + const client = c.client(); + await client.coordinator.getOrCreate("main").reportResult(result); + }, + }, +}); +``` + + + + +```ts +const coordinator = client.coordinator.getOrCreate("main"); + +// Start a job with multiple tasks +await coordinator.startJob([ + { id: "task-1", data: "..." }, + { id: "task-2", data: "..." }, + { id: "task-3", data: "..." }, +]); + +// Results are collected as workers report back +const results = await coordinator.getResults(); +``` + + + + +## State Loading From External Resources + +Load external data during actor initialization using `createVars`. This keeps your actor's persisted state clean while caching expensive lookups. + +**When to use:** +- Fetching user profiles, configs, or permissions from a database +- Loading data that changes externally and shouldn't be persisted + +**Example: Loading User Data** + + + + +```ts +const userSession = actor({ + state: { activityLog: [] as string[] }, + + createVars: async (c) => { + // Load from database on every wake + const user = await db.users.findById(c.id); + return { user }; + }, + + actions: { + getProfile: (c) => c.vars.user, + updatePreference: async (c, key: string, value: string) => { + await db.users.update(c.id, { [key]: value }); + // Refresh cached data + c.vars.user = await db.users.findById(c.id); + }, + }, +}); +``` + + + + +```ts +const session = client.userSession.getOrCreate("user-123"); + +// Get profile (loaded from database on actor wake) +const profile = await session.getProfile(); + +// Update preference (writes to database and refreshes cache) +await session.updatePreference("theme", "dark"); +``` + + + + +`createVars` runs on every wake (after restarts, crashes, or sleep), so external data stays fresh. + +## Anti-Patterns + +### "God" Actor + +Avoid creating a single actor that handles everything. This defeats the purpose of the actor model and creates a bottleneck. + +**Problem:** +```ts +// Bad: one actor doing everything +const app = actor({ + state: { users: {}, orders: {}, inventory: {}, analytics: {} }, + actions: { + createUser: (c, user) => { /* ... */ }, + processOrder: (c, order) => { /* ... */ }, + updateInventory: (c, item) => { /* ... */ }, + trackEvent: (c, event) => { /* ... */ }, + }, +}); +``` + +**Solution:** Split into focused actors per entity (User, Order, Inventory, Analytics). + +### Actor-Per-Request + +Actors are designed to maintain state across multiple requests. Creating a new actor for each request wastes resources and loses the benefits of persistent state. + +**Problem:** +```ts +// Bad: creating an actor for each API request +app.post("/process", async (req) => { + const actor = client.processor.getOrCreate(crypto.randomUUID()); + const result = await actor.process(req.body); + await actor.destroy(); + return result; +}); +``` + +**Solution:** Use actors for entities that persist (users, sessions, documents), not for one-off operations. For stateless request handling, use regular functions. + diff --git a/website/src/content/docs/actors/destroy.mdx b/website/src/content/docs/actors/destroy.mdx new file mode 100644 index 0000000000..c103c1ad19 --- /dev/null +++ b/website/src/content/docs/actors/destroy.mdx @@ -0,0 +1,108 @@ +# Destroying Actors + +Actors can be permanently destroyed. Common use cases include: + +- User account deletion +- Ending a user session +- Closing a room or game +- Cleaning up temporary resources +- GDPR/compliance data removal + +Actors sleep when idle, so destruction is only needed to permanently remove data — not to save compute. + +## Destroying An Actor + +### Destroy via Action + +To destroy an actor, use `c.destroy()` like this: + +```typescript +import { actor } from "rivetkit"; + +interface UserInput { + email: string; + name: string; +} + +const userActor = actor({ + createState: (c, input: UserInput) => ({ + email: input.email, + name: input.name, + }), + actions: { + deleteAccount: (c) => { + c.destroy(); + }, + }, +}); +``` + +### Destroy via HTTP + +Send a DELETE request to destroy an actor. This requires an admin token for authentication. + + + +```typescript +await fetch(`https://api.rivet.dev/actors/${actorId}?namespace=${namespace}`, { + method: "DELETE", + headers: { + Authorization: `Bearer ${token}`, + }, +}); +``` + +```bash +curl -X DELETE "https://api.rivet.dev/actors/{actorId}?namespace={namespace}" \ + -H "Authorization: Bearer {token}" +``` + + + + Creating admin tokens is currently not supported on Rivet Cloud. See the [tracking issue](https://github.com/rivet-dev/rivet/issues/3530). + + +### Destroy via Dashboard + +To destroy an actor via the dashboard, navigate to the actor and press the red "X" in the top right. + +## Lifecycle Hook + +Once destroyed, the `onDestroy` hook will be called. This can be used to clean up resources related to the actor. For example: + +```typescript +import { actor } from "rivetkit"; +import { Resend } from "resend"; + +const resend = new Resend(process.env.RESEND_API_KEY); + +interface UserInput { + email: string; + name: string; +} + +const userActor = actor({ + createState: (c, input: UserInput) => ({ + email: input.email, + name: input.name, + }), + onDestroy: async (c) => { + await resend.emails.send({ + from: "noreply@example.com", + to: c.state.email, + subject: "Account Deleted", + text: `Goodbye ${c.state.name}, your account has been deleted.`, + }); + }, + actions: { + deleteAccount: (c) => { + c.destroy(); + }, + }, +}); +``` + +## Accessing Actor After Destroy + +Once an actor is destroyed, any subsequent requests to it will return an `actor_not_found` error. The actor's state is permanently deleted. + diff --git a/website/src/content/docs/actors/errors.mdx b/website/src/content/docs/actors/errors.mdx new file mode 100644 index 0000000000..fdf83d2a53 --- /dev/null +++ b/website/src/content/docs/actors/errors.mdx @@ -0,0 +1,4 @@ +# Errors + +TODO + diff --git a/website/src/content/docs/actors/events.mdx b/website/src/content/docs/actors/events.mdx index 597b556fc8..9f1ab8d388 100644 --- a/website/src/content/docs/actors/events.mdx +++ b/website/src/content/docs/actors/events.mdx @@ -2,7 +2,7 @@ Events enable real-time communication from actors to clients. While clients use actions to send data to actors, events allow actors to push updates to connected clients instantly. -Events work through persistent connections such as WebSocket or SSE. +Events can be sent to clients connected using `.connect()`. They have no effect on [low-level WebSocket connections](/docs/actors/websocket-handler). ## Publishing Events from Actors diff --git a/website/src/content/docs/actors/external-sql.mdx b/website/src/content/docs/actors/external-sql.mdx index 9cf36b027c..e4a33e6ab2 100644 --- a/website/src/content/docs/actors/external-sql.mdx +++ b/website/src/content/docs/actors/external-sql.mdx @@ -63,7 +63,7 @@ export const userActor = actor({ }), // Insert user into database when actor starts - onStart: async (c, opts) => { + onWake: async (c, opts) => { const result = await pool.query( "INSERT INTO users (username, email, created_at) VALUES ($1, $2, $3)", [c.state.username, c.state.email, c.state.lastActive] @@ -177,7 +177,7 @@ export const userActor = actor({ }), // Insert user into database when actor starts - onStart: async (c, opts) => { + onWake: async (c, opts) => { const result = await db.insert(users).values({ username: c.state.username, email: c.state.email, diff --git a/website/src/content/docs/actors/fetch-and-websocket-handler.mdx b/website/src/content/docs/actors/fetch-and-websocket-handler.mdx index 15faad7810..1b74780362 100644 --- a/website/src/content/docs/actors/fetch-and-websocket-handler.mdx +++ b/website/src/content/docs/actors/fetch-and-websocket-handler.mdx @@ -1,586 +1,4 @@ # Fetch and WebSocket Handler -Actors can handle HTTP requests and WebSocket connections through the `onFetch` and `onWebSocket` handlers. - -For most use cases, [actions](/docs/actors/actions) and [events](/docs/actors/events) provide high-level connection handling that's easier to work with. However, raw handlers are required when implementing custom use cases or integrating external libraries that need direct access to the underlying HTTP `Request`/`Response` objects or WebSocket connections. - -## Defining Handlers - -### `onFetch(c, request, { auth })` - -The `onFetch` handler processes HTTP requests sent to your actor. It receives the actor context and a standard `Request` object. - -WebSocket upgrades are not currently supported in `onFetch`. Use `onWebSocket` instead. - - - - -```typescript -import { type ActorContext, actor } from "@rivetkit/core"; - -export const httpActor = actor({ - state: { - requestCount: 0, - }, - actions: {}, - onFetch(ctx, request) { - const url = new URL(request.url); - ctx.state.requestCount++; - - if (url.pathname === "/api/hello") { - return new Response(JSON.stringify({ message: "Hello from actor!" }), { - headers: { "Content-Type": "application/json" }, - }); - } - - if (url.pathname === "/api/echo" && request.method === "POST") { - return new Response(request.body, { - headers: request.headers, - }); - } - - // Return 404 for unhandled paths - return new Response("Not Found", { status: 404 }); - }, -}); -``` - - - - -```typescript -import { type ActorContext, actor } from "@rivetkit/core"; -import { Hono } from "hono"; - -function buildRouter(ctx: ActorContext<{ requestCount: number }>) { - const app = new Hono(); - - // Set up Hono routes - app.get("/api/hello", (c) => { - return c.json({ message: "Hello from Hono!" }); - }); - - app.post("/api/echo", async (c) => { - const body = await c.req.json(); - return c.json(body); - }); - - app.get("/api/stats", (c) => { - return c.json({ requestCount: ctx.state.requestCount }); - }); - - return app; -} - -export const honoActor = actor({ - state: { - requestCount: 0, - }, - createVars(ctx) { - const app = buildRouter(ctx); - return { app }; - }, - actions: {}, - async onFetch(ctx, request) { - ctx.state.requestCount++; - - // Pass request to Hono app - return await ctx.vars.app.fetch(request); - }, -}); -``` - - - - -Also see the [raw fetch handler example project](https://github.com/rivet-dev/rivetkit/tree/main/examples/raw-fetch-handler). - - - `onFetch` can be used to expose Server-Sent Events from Rivet Actors. - - -### `onWebSocket(c, websocket, { request, auth })` - -The `onWebSocket` handler manages WebSocket connections. It receives the actor context, a `WebSocket` object, and the initial `Request`. - -```typescript -export const websocketActor = actor({ - state: { messageCount: 0 }, - actions: {}, - onWebSocket(ctx, websocket) { - websocket.send(JSON.stringify({ - type: "welcome", - connectionCount: ctx.state.connectionCount, - })); - - websocket.addEventListener("message", (event) => { - c.state.messageCount++; - - // Echo messages back - websocket.send(event.data); - }); - }, -}); -``` - -Also see the [raw WebSocket handler with proxy example project](https://github.com/rivet-dev/rivetkit/tree/main/examples/raw-websocket-handler-proxy). - - - Connection lifecycle hooks like `onConnect` and `onDisconnect` do not get called when opening WebSockets for `onWebSocket`. This is because `onWebSocket` provides a low-level connection. Use `ws.addEventListener("open")` and `ws.addEventListener("close")` instead. - - -## Accessing Your Handlers - -There are three ways to access your actor's fetch and WebSocket handlers: - -### Option A: From Backend via RivetKit Client - -You can use the RivetKit client's built-in methods for raw HTTP and WebSocket access: - - - - -```typescript -import { createClient } from "@rivetkit/core/client"; - -const client = createClient("http://localhost:8080"); - -// HTTP requests using .fetch() method -const actor = client.myActor.getOrCreate(["key"]); -const response = await actor.fetch("/api/hello", { // Also accepts W3C `Request` object - method: "GET" -}); -const data = await response.json(); - -// POST request with JSON body -const postResponse = await actor.fetch("/api/echo", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ message: "Hello from client!" }), -}); -``` - - - - -```typescript -import { createClient } from "@rivetkit/core/client"; - -const client = createClient("http://localhost:8080"); - -// WebSocket connections using .websocket() method -const actor = client.myActor.getOrCreate(["key"]); -const ws = await actor.websocket("/custom/path"); - -// Listen for messages -ws.addEventListener("message", (event) => { - const message = JSON.parse(event.data); - console.log("Received:", message); - - if (message.type === "welcome") { - console.log("Connected! Connection count:", message.connectionCount); - } else if (message.type === "echo") { - console.log("Echo received:", message.data); - } else if (message.type === "pong") { - console.log("Pong received at:", message.timestamp); - } -}); - -// Send messages -ws.send(JSON.stringify({ - type: "echo", - data: "Hello from client!" -})); - -// Send ping -ws.send(JSON.stringify({ - type: "ping" -})); -``` - - - - -For more advanced use cases, you can forward requests to actor handlers from your server: - - - - -```typescript -import { Hono } from "hono"; -import { registry } from "./registry"; -import { serve } from "@hono/node-server"; - -const { client } = registry.start(); - -const app = new Hono(); - -// Forward requests to actor's fetch handler -app.all("/forward/:name/*", async (c) => { - const name = c.req.param("name"); - - // Create new URL with the path truncated - const truncatedPath = c.req.path.replace(`/forward/${name}`, ""); - const url = new URL(truncatedPath, c.req.url); - const newRequest = new Request(url, c.req.raw); - - // Forward to actor's fetch handler - const actor = client.counter.getOrCreate(name); - const response = await actor.fetch(truncatedPath, newRequest); - - return response; -}); - -serve(app); -``` - - - - -```typescript -import { Hono } from "hono"; -import { upgradeWebSocket } from "hono/ws"; -import { serve } from "@hono/node-server"; -import { registry } from "./registry"; - -const { client } = registry.start(); - -const app = new Hono(); - -// Forward WebSocket connections to actor's WebSocket handler -app.get("/ws/:name", upgradeWebSocket(async (c) => { - const name = c.req.param("name"); - - // Connect to WebSocket - const actor = client.counter.getOrCreate(name); - let actorWs = await actor.websocket("/"); - - return { - onOpen: async (evt, ws) => { - // Bridge actor WebSocket to client WebSocket - actorWs.addEventListener("message", (event) => { - ws.send(event.data); - }); - - actorWs.addEventListener("close", () => { - ws.close(); - }); - }, - onMessage: (evt, ws) => { - // Forward message to actor WebSocket - actorWs.send(evt.data); - }, - onClose: (evt, ws) => { - // Forward close to actor WebSocket - actorWs.close(); - }, - }; -})); - -serve(app); -``` - - - - -### Option B: From Frontend with RivetKit Client - -Use the RivetKit client to make direct HTTP requests or WebSocket connections: - - - - -```typescript -import { createClient } from "@rivetkit/core/client"; - -const client = createClient("http://localhost:8080"); - -// HTTP requests -const actor = client.myActor.getOrCreate(["key"]); -const response = await actor.fetch("/api/hello", { // Also accepts W3C `Request` object - method: "GET" -}); -const data = await response.json(); -console.log(data); // { message: "Hello from actor!" } - -// POST request with data -const postResponse = await actor.fetch("/api/echo", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - message: "Hello from frontend!", - timestamp: Date.now() - }), -}); - -// Handle response -if (postResponse.ok) { - const echoData = await postResponse.json(); - console.log("Echo response:", echoData); -} else { - console.error("Request failed:", postResponse.status); -} -``` - - - - -```typescript -import { createClient } from "@rivetkit/core/client"; - -const client = createClient("http://localhost:8080"); - -// WebSocket connections -const actor = client.myActor.getOrCreate(["key"]); -const ws = await actor.websocket("/"); - -// Listen for messages -ws.addEventListener("message", (event) => { - const message = JSON.parse(event.data); - - switch (message.type) { - case "welcome": - console.log("Connected! Stats:", { - connectionCount: message.connectionCount, - messageCount: message.messageCount - }); - break; - - case "echo": - console.log("Echo received:", message.data); - displayMessage(message.data); - break; - - case "pong": - console.log("Pong received, latency:", Date.now() - message.timestamp); - break; - - case "error": - console.error("Error:", message.message); - break; - } -}); - -// Send messages -function sendMessage(text) { - ws.send(JSON.stringify({ - type: "echo", - data: text - })); -} - -// Ping for latency testing -function ping() { - ws.send(JSON.stringify({ - type: "ping" - })); -} - -// Handle connection errors -ws.addEventListener("error", (event) => { - console.error("WebSocket error:", event); -}); - -ws.addEventListener("close", () => { - console.log("WebSocket connection closed"); -}); -``` - - - The `.websocket()` method returns a barebones WebSocket. Unlike [actor connections](/docs/actors/connections), it does not provide automatic reconnection logic. You must implement reconnection logic yourself if needed. - - - - - -### Option C: From Frontend via Direct RivetKit Router Access - -You can access your actor handlers directly through the mounted RivetKit router. The router automatically handles the required headers for authentication and routing. - - - - -For HTTP requests, the router expects these headers: -- `X-RivetKit-Actor-Query`: JSON-encoded actor query -- `X-RivetKit-Encoding`: Encoding type (usually "json") -- `X-RivetKit-Conn-Params`: JSON-encoded connection parameters (optional) - -```typescript -// Direct HTTP request to actor -const response = await fetch("http://localhost:8080/registry/actors/myActor/request/api/hello", { - method: "GET", - headers: { - "X-RivetKit-Actor-Query": JSON.stringify({ - getOrCreateForKey: { name: "myActor", key: "default" } - }), - "X-RivetKit-Encoding": "json", - "X-RivetKit-Conn-Params": JSON.stringify({ apiKey: "your-api-key" }) - } -}); - -const data = await response.json(); -console.log(data); // { message: "Hello from actor!" } - -// POST request with data -const postResponse = await fetch("http://localhost:8080/registry/actors/myActor/request/api/echo", { - method: "POST", - headers: { - "X-RivetKit-Actor-Query": JSON.stringify({ - getOrCreateForKey: { name: "myActor", key: "default" } - }), - "X-RivetKit-Encoding": "json", - "X-RivetKit-Conn-Params": JSON.stringify({ apiKey: "your-api-key" }), - "Content-Type": "application/json" - }, - body: JSON.stringify({ - message: "Hello from direct access!", - timestamp: Date.now() - }) -}); - -// Handle response -if (postResponse.ok) { - const echoData = await postResponse.json(); - console.log("Echo response:", echoData); -} else { - console.error("Request failed:", postResponse.status); -} -``` - - - - -For WebSocket connections, authentication data is passed via WebSocket subprotocols: - -```typescript -// Direct WebSocket connection to actor -const protocols = [ - `query.${encodeURIComponent(JSON.stringify({ - getOrCreateForKey: { name: "myActor", key: "default" } - }))}`, - `encoding.json`, - `conn_params.${encodeURIComponent(JSON.stringify({ apiKey: "your-api-key" }))}` -]; - -const ws = new WebSocket("ws://localhost:8080/registry/actors/myActor/ws/", protocols); - -// Listen for messages -ws.addEventListener("message", (event) => { - const message = JSON.parse(event.data); - - switch (message.type) { - case "welcome": - console.log("Connected via direct access!", { - connectionCount: message.connectionCount, - messageCount: message.messageCount - }); - - // Send initial message - ws.send(JSON.stringify({ - type: "echo", - data: "Hello from direct WebSocket access!" - })); - break; - - case "echo": - console.log("Echo received:", message.data); - break; - - case "pong": - console.log("Pong received, latency:", Date.now() - message.timestamp); - break; - - case "error": - console.error("WebSocket error:", message.message); - break; - } -}); - -// Send ping for latency testing -function sendPing() { - ws.send(JSON.stringify({ - type: "ping" - })); -} - -// Handle connection events -ws.addEventListener("open", () => { - console.log("WebSocket connected via direct access"); -}); - -ws.addEventListener("error", (event) => { - console.error("WebSocket error:", event); -}); - -ws.addEventListener("close", (event) => { - console.log("WebSocket closed:", event.code, event.reason); -}); -``` - - - For Cloudflare Workers, you must include `"rivetkit"` as a protocol when using raw WebSockets: - - ```typescript - const protocols = [ - "rivetkit", // Required for Cloudflare Workers - `query.${encodeURIComponent(JSON.stringify({ - getOrCreateForKey: { name: "myActor", key: "default" } - }))}`, - `encoding.json` - ]; - ``` - - - - - -## Authentication - -If you are using the external client, authentication is handled through the `onAuth` handler. The `onAuth` handler is executed on the server before the request is sent to the actor, reducing resource load on the actor by filtering out unauthorized requests early. - -If you are using the server-side client, then authentication is skipped by default. - -See the [authentication documentation](/docs/actors/authentication) for detailed information on implementing authentication patterns. - - -## State Saves - -State changes in `onFetch` and `onWebSocket` handlers are automatically saved after the handler finishes executing. - -For `onWebSocket` handlers specifically, you'll need to manually save state using `c.saveState()` while the WebSocket connection is open if you want state changes to be persisted immediately. This is because WebSocket connections can remain open for extended periods, and state changes made during event handlers (like `message` events) won't be automatically saved until the connection closes. - -```typescript -export const websocketActor = actor({ - state: { messageCount: 0, lastMessage: "" }, - actions: {}, - onWebSocket(ctx, websocket) { - websocket.addEventListener("message", (event) => { - // Update state - ctx.state.messageCount++; - ctx.state.lastMessage = event.data; - - // Manually save state to persist changes immediately - ctx.saveState(); - - // Echo messages back - websocket.send(JSON.stringify({ - messageCount: ctx.state.messageCount, - echo: event.data - })); - }); - }, -}); -``` - -For more details on state management, see [State](/docs/actors/state). - -## W3C Compliance - -It's not possible to use the global `fetch` method or global WebSocket class to connect to an actor. This is because actors do not have traditional network interfaces to communicate with. - -However, the `Request`, `Response`, and `WebSocket` types used with `.fetch()` and `.websocket()` comply with the W3C specification and will work wherever you pass them. +These docs have moved to [Low-Level WebSocket Handler](/docs/actors/websocket-handler) and [Low-Level Request Handler](/docs/actors/request-handler). diff --git a/website/src/content/docs/actors/helper-types.mdx b/website/src/content/docs/actors/helper-types.mdx index e6fa5729a0..68e877128f 100644 --- a/website/src/content/docs/actors/helper-types.mdx +++ b/website/src/content/docs/actors/helper-types.mdx @@ -17,7 +17,7 @@ import { actor, ActorContextOf } from "rivetkit"; const chatRoom = actor({ state: { messages: [] }, actions: { - onStart: (c, message) => { + onWake: (c, message) => { // Can ActorContext be used in lifecycle hooks exampleFunction(c, "Actor started"); }, diff --git a/website/src/content/docs/actors/http-api.mdx b/website/src/content/docs/actors/http-api.mdx new file mode 100644 index 0000000000..9af603f146 --- /dev/null +++ b/website/src/content/docs/actors/http-api.mdx @@ -0,0 +1,4 @@ +# Vanilla HTTP API + +TODO + diff --git a/website/src/content/docs/actors/index.mdx b/website/src/content/docs/actors/index.mdx index 593115f4a3..eb5ee51c44 100644 --- a/website/src/content/docs/actors/index.mdx +++ b/website/src/content/docs/actors/index.mdx @@ -4,43 +4,14 @@ import { faCloudflare, faNodeJs, faReact, faNextjs } from "@rivet-gg/icons"; Actors for long-lived processes with durable state, realtime, and hibernate when not in use. -## Quickstart - - - - Set up Rivet with Node.js, Bun, and web frameworks - - - Set up Rivet with React - - - Set up Rivet with Next.js - - - Set up Rivet with Cloudflare Workers - - - ## Features - **Long-Lived, Stateful Compute**: Each unit of compute is like a tiny server that remembers things between requests – no need to re-fetch data from a database or worry about timeouts. Like AWS Lambda, but with memory and no timeouts. - **Blazing-Fast Reads & Writes**: State is stored on the same machine as your compute, so reads and writes are ultra-fast. No database round trips, no latency spikes. -- **Realtime**: Update state and broadcast changes in realtime with WebSockets or SSE. No external pub/sub systems, no polling – just built-in low-latency events. +- **Realtime**: Update state and broadcast changes in realtime with WebSockets. No external pub/sub systems, no polling – just built-in low-latency events. - **Infinitely Scalable**: Automatically scale from zero to millions of concurrent actors. Pay only for what you use with instant scaling and no cold starts. - **Fault Tolerant**: Built-in error handling and recovery. Actors automatically restart on failure while preserving state integrity and continuing operations. -## Use Cases - -Actors are perfect for applications that need persistent state and real-time updates: - -- **AI agents**: Stateful AI assistants with conversation history -- **Collaborative documents**: Multiple users editing documents simultaneously (Yjs integration) -- **Local-first sync**: Offline-first applications with server synchronization -- **Per-tenant databases**: Isolated data stores for each user or tenant -- **Background job**: Background & time-based task execution with persistent state -- **Rate limiting**: Distributed rate limiting with persistent counters -- **Stream processing**: Real-time data processing with persistent state - ## Core Concepts ### State Management @@ -100,7 +71,7 @@ Learn more about [actions](/docs/actors/actions) and [communicating with actors] ### Real-time Communication & Events -Actors support real-time bidirectional communication through WebSocket and SSE connections. Clients can establish persistent connections to receive live updates. +Actors support real-time bidirectional communication through WebSocket connections. Clients can establish persistent connections to receive live updates. For example, to send events to all connected clients: @@ -194,30 +165,3 @@ const foundUser = await manager.getUser(user.userId); -## Frequently Asked Questions - - - - Some software makes sense to separate – e.g., for data lakes or highly relational data. But at the end of the day, data has to be partitioned somewhere at some point. - - Usually "faster" databases like Cassandra, DynamoDB, or Vitess make consistency tradeoffs to get better performance. Stateful serverless forces you to think about how your data is sharded for better performance, better scalability, and less consistency footguns. - - - - See [Sharing and Joining State](/docs/actors/sharing-and-joining-state) for detailed strategies on combining data from multiple actors. - - - - OLAP, data lakes, graph databases, and highly relational data are currently not ideal use cases for the actor model. - - - - Yes, but only in the same way that storing data in a single database row creates a bottleneck. - - Just like a single database row can cause contention when multiple clients try to read and write the same data, a single actor can become a bottleneck if too many requests target it. - - The solution is the same: shard your data across multiple actors to distribute the load and scale seamlessly. - - However, actors handle much higher throughput than traditional database rows because they keep data in memory, making read and write operations significantly faster. - - diff --git a/website/src/content/docs/actors/lifecycle.mdx b/website/src/content/docs/actors/lifecycle.mdx index dbc65d1743..bef518b292 100644 --- a/website/src/content/docs/actors/lifecycle.mdx +++ b/website/src/content/docs/actors/lifecycle.mdx @@ -4,108 +4,154 @@ Understand actor lifecycle hooks and initialization patterns Actors follow a well-defined lifecycle with hooks at each stage. Understanding these hooks is essential for proper initialization, state management, and cleanup. +## Lifecycle + +Actors transition through several states during their lifetime. Each transition triggers specific hooks that let you initialize resources, manage connections, and clean up state. + +**On Create** (first time only) + +- `createState` +- `onCreate` +- `createVars` +- `onWake` + +**On Wake** (after sleep, restart, or crash) + +- `createVars` +- `onWake` + +**On Sleep** + +- `onSleep` + +**On Destroy** + +- `onDestroy` + +**On Connect** (per client) + +- `onBeforeConnect` +- `createConnState` +- `onConnect` + +**On Disconnect** (per client) + +- `onDisconnect` ## Lifecycle Hooks Actor lifecycle hooks are defined as functions in the actor configuration. -### `createState` and `state` +### `state` -{/* [Documentation](https://jsr.io/@rivet-gg/actor/doc/~/Actor.prototype._onInitialize) */} +The `state` constant defines the initial state of the actor. See [state documentation](/docs/actors/state) for more information. -The `createState` function or `state` constant defines the initial state of the actor (see [state documentation](/docs/actors/state)). The `createState` function is called only once when the actor is first created. +```typescript +import { actor } from "rivetkit"; -### `createVars` and `vars` +const counter = actor({ + state: { count: 0 }, + actions: { /* ... */ } +}); +``` -The `createVars` function or `vars` constant defines ephemeral variables for the actor (see [state documentation](/docs/actors/state)). These variables are not persisted and are useful for storing runtime-only objects or temporary data. +### `createState` -The `createVars` function can also receive driver-specific context as its second parameter, allowing access to driver capabilities like Rivet KV or Cloudflare Durable Object storage. +`createState(c: ActorContext, input: TInput): TState | Promise` + +The `createState` function dynamically initializes state based on input. Called only once when the actor is first created. Can be async. See [state documentation](/docs/actors/state) for more information. ```typescript -import { actor, ActorInitContext } from "rivetkit"; -// In this example, assume we're using Redis -import type { DriverContext } from "@rivetkit/redis"; +import { actor } from "rivetkit"; -// Using vars constant -const counter1 = actor({ - state: { count: 0 }, - vars: { lastAccessTime: 0 }, +const counter = actor({ + createState: (c, input: { initialCount: number }) => ({ + count: input.initialCount + }), actions: { /* ... */ } }); +``` + +### `vars` + +The `vars` constant defines ephemeral variables for the actor. These variables are not persisted and are useful for storing runtime-only data. The value for `vars` must be clonable via `structuredClone`. See [ephemeral variables documentation](/docs/actors/state#ephemeral-variables-vars) for more information. + +```typescript +import { actor } from "rivetkit"; -// Using createVars function -const counter2 = actor({ +const counter = actor({ state: { count: 0 }, - createVars: () => { - // Initialize with non-serializable objects - return { - lastAccessTime: Date.now(), - emitter: new EventTarget() - }; - }, + vars: { lastAccessTime: 0 }, actions: { /* ... */ } }); +``` + +### `createVars` + +`createVars(c: InitContext, driverCtx: any): TVars | Promise` -// Access driver-specific context -const exampleActor = actor({ +The `createVars` function dynamically initializes ephemeral variables. Can be async. Use this when you need to initialize values at runtime. The `driverCtx` parameter provides driver-specific context. See [ephemeral variables documentation](/docs/actors/state#ephemeral-variables-vars) for more information. + +```typescript +import { actor } from "rivetkit"; + +interface CounterVars { + lastAccessTime: number; + emitter: EventTarget; +} + +const counter = actor({ state: { count: 0 }, - // Access driver context in createVars - createVars: (c: ActorInitContext, driverCtx: DriverContext) => ({ - driverCtx, + createVars: (c, driverCtx): CounterVars => ({ + lastAccessTime: Date.now(), + emitter: new EventTarget() }), - actions: { - doSomething: (c) => { - // Use driver-specific context - console.log("Driver context:", c.vars.driverCtx); - } - } + actions: { /* ... */ } }); ``` ### `onCreate` -The `onCreate` hook is called at the same time as `createState`, but unlike `createState`, it doesn't return any value. Use this hook for initialization logic that doesn't affect the initial state. +`onCreate(c: ActorContext, input: TInput): void | Promise` + +The `onCreate` hook is called when the actor is first created. Can be async. Use this hook for initialization logic that doesn't affect the initial state. ```typescript import { actor } from "rivetkit"; -// Using state constant -const counter1 = actor({ +const counter = actor({ state: { count: 0 }, - actions: { /* ... */ } -}); -// Using createState function -const counter2 = actor({ - createState: () => { - // Initialize with a count of 0 - return { count: 0 }; + onCreate: (c, input: { initialCount: number }) => { + console.log("Actor created with initial count:", input.initialCount); }, + actions: { /* ... */ } }); +``` -// Using onCreate -const counter3 = actor({ - state: { count: 0 }, - - // Run initialization logic (logging, external service setup, etc.) - onCreate: (c, opts, input: { foo: string }) => { - console.log("Counter actor initialized"); - // Access input parameters if provided - console.log("Input:", input); - // Can perform async operations or setup - // No need to return anything +### `onDestroy` + +`onDestroy(c: ActorContext): void | Promise` + +The `onDestroy` hook is called when the actor is being permanently destroyed. Can be async. Use this for final cleanup operations like closing external connections, releasing resources, or performing any last-minute state persistence. + +```typescript +import { actor } from "rivetkit"; + +const gameSession = actor({ + onDestroy: (c) => { + // Clean up any external resources }, - actions: { /* ... */ } }); ``` -### `onStart` +### `onWake` -{/* [Documentation](https://jsr.io/@rivet-gg/actor/doc/~/Actor.prototype._onStart) */} +`onWake(c: ActorContext): void | Promise` -This hook is called any time the actor is started (e.g. after restarting, upgrading code, or crashing). +This hook is called any time the actor is started (e.g. after restarting, upgrading code, or crashing). Can be async. This is called after the actor has been initialized but before any connections are accepted. @@ -117,22 +163,22 @@ import { actor } from "rivetkit"; const counter = actor({ state: { count: 0 }, vars: { intervalId: null as NodeJS.Timeout | null }, - - onStart: (c) => { + + onWake: (c) => { console.log('Actor started with count:', c.state.count); - + // Set up interval for automatic counting const intervalId = setInterval(() => { c.state.count++; c.broadcast("countChanged", c.state.count); console.log('Auto-increment:', c.state.count); }, 10000); - + // Store interval ID in vars to clean up later if needed c.vars.intervalId = intervalId; }, - - actions: { + + actions: { stop: (c) => { if (c.vars.intervalId) { clearInterval(c.vars.intervalId); @@ -143,18 +189,58 @@ const counter = actor({ }); ``` +### `onSleep` + +`onSleep(c: ActorContext): void | Promise` + +This hook is called when the actor is going to sleep. Can be async. Use this to clean up resources, close connections, or perform any shutdown operations. + +Not supported on all platforms. + +```typescript +import { actor } from "rivetkit"; + +const counter = actor({ + state: { count: 0 }, + vars: { intervalId: null as NodeJS.Timeout | null }, + + onWake: (c) => { + // Set up interval when actor wakes + c.vars.intervalId = setInterval(() => { + c.state.count++; + console.log('Auto-increment:', c.state.count); + }, 10000); + }, + + onSleep: (c) => { + console.log('Actor going to sleep, cleaning up...'); + + // Clean up interval before sleeping + if (c.vars.intervalId) { + clearInterval(c.vars.intervalId); + c.vars.intervalId = null; + } + + // Perform any other cleanup + console.log('Final count:', c.state.count); + }, + + actions: { /* ... */ } +}); +``` + ### `onStateChange` -{/* [Documentation](https://jsr.io/@rivet-gg/actor/doc/~/Actor.prototype._onStateChange) */} +`onStateChange(c: ActorContext, newState: TState): void` -Called whenever the actor's state changes. This is often used to broadcast state updates. +Called whenever the actor's state changes. Cannot be async. This is often used to broadcast state updates. ```typescript import { actor } from "rivetkit"; const counter = actor({ state: { count: 0 }, - + onStateChange: (c, newState) => { // Broadcast the new count to all connected clients c.broadcast('countUpdated', { @@ -173,17 +259,17 @@ const counter = actor({ ### `createConnState` and `connState` -{/* [Documentation](https://jsr.io/@rivet-gg/actor/doc/~/Actor.prototype._createConnState) */} +`createConnState(c: CreateConnStateContext, params: TConnParams): TConnState | Promise` There are two ways to define the initial state for connections: 1. `connState`: Define a constant object that will be used as the initial state for all connections -2. `createConnState`: A function that dynamically creates initial connection state based on connection parameters +2. `createConnState`: A function that dynamically creates initial connection state based on connection parameters. Can be async. ### `onBeforeConnect` -{/* [Documentation](https://jsr.io/@rivet-gg/actor/doc/~/Actor.prototype._onBeforeConnect) */} +`onBeforeConnect(c: OnBeforeConnectContext, params: TConnParams): void | Promise` -The `onBeforeConnect` hook is called whenever a new client connects to the actor. Clients can pass parameters when connecting, accessible via `params`. This hook is used for connection validation and can throw errors to reject connections. +The `onBeforeConnect` hook is called whenever a new client connects to the actor. Can be async. Clients can pass parameters when connecting, accessible via `params`. This hook is used for connection validation and can throw errors to reject connections. The `onBeforeConnect` hook does NOT return connection state - it's used solely for validation. @@ -192,34 +278,34 @@ import { actor } from "rivetkit"; const chatRoom = actor({ state: { messages: [] }, - + // Method 1: Use a static default connection state connState: { role: "guest", joinTime: 0, }, - + // Method 2: Dynamically create connection state - createConnState: (c, opts, params: { userId?: string, role?: string }) => { + createConnState: (c, params: { userId?: string, role?: string }) => { return { userId: params.userId || "anonymous", role: params.role || "guest", joinTime: Date.now() }; }, - + // Validate connections before accepting them - onBeforeConnect: (c, opts, params: { authToken?: string }) => { + onBeforeConnect: (c, params: { authToken?: string }) => { // Validate authentication const authToken = params.authToken; if (!authToken || !validateToken(authToken)) { throw new Error("Invalid authentication"); } - + // Authentication is valid, connection will proceed // The actual connection state will come from connState or createConnState }, - + actions: { /* ... */ } }); ``` @@ -228,30 +314,30 @@ Connections cannot interact with the actor until this method completes successfu ### `onConnect` -{/* [Documentation](https://jsr.io/@rivet-gg/actor/doc/~/Actor.prototype._onConnect) */} +`onConnect(c: OnConnectContext, conn: Conn): void | Promise` -Executed after the client has successfully connected. +Executed after the client has successfully connected. Can be async. Receives the connection object as a second parameter. ```typescript import { actor } from "rivetkit"; const chatRoom = actor({ state: { users: {}, messages: [] }, - - onConnect: (c) => { + + onConnect: (c, conn) => { // Add user to the room's user list using connection state - const userId = c.conn.state.userId; + const userId = conn.state.userId; c.state.users[userId] = { online: true, lastSeen: Date.now() }; - + // Broadcast that a user joined c.broadcast("userJoined", { userId, timestamp: Date.now() }); - + console.log(`User ${userId} connected`); }, - + actions: { /* ... */ } }); ``` @@ -260,48 +346,52 @@ Messages will not be processed for this actor until this hook succeeds. Errors t ### `onDisconnect` -{/* [Documentation](https://jsr.io/@rivet-gg/actor/doc/~/Actor.prototype._onDisconnect) */} +`onDisconnect(c: ActorContext, conn: Conn): void | Promise` -Called when a client disconnects from the actor. Use this to clean up any connection-specific resources. +Called when a client disconnects from the actor. Can be async. Receives the connection object as a second parameter. Use this to clean up any connection-specific resources. ```typescript import { actor } from "rivetkit"; const chatRoom = actor({ state: { users: {}, messages: [] }, - - onDisconnect: (c) => { + + onDisconnect: (c, conn) => { // Update user status when they disconnect - const userId = c.conn.state.userId; + const userId = conn.state.userId; if (c.state.users[userId]) { c.state.users[userId].online = false; c.state.users[userId].lastSeen = Date.now(); } - + // Broadcast that a user left c.broadcast("userLeft", { userId, timestamp: Date.now() }); - + console.log(`User ${userId} disconnected`); }, - + actions: { /* ... */ } }); ``` -### `onFetch` +### `onRequest` -The `onFetch` hook handles HTTP requests sent to your actor. It receives the actor context and a standard `Request` object, and should return a `Response` object or `void` to continue default routing. +`onRequest(c: RequestContext, request: Request): Response | Promise` + +The `onRequest` hook handles HTTP requests sent to your actor at `/actors/{actorName}/http/*` endpoints. Can be async. It receives the request context and a standard `Request` object, and should return a `Response` object or `void` to continue default routing. + +See [Request Handler](/docs/actors/request-handler) for more details. ```typescript import { actor } from "rivetkit"; const apiActor = actor({ state: { requestCount: 0 }, - - onFetch: (c, request) => { + + onRequest: (c, request) => { const url = new URL(request.url); c.state.requestCount++; - + if (url.pathname === "/api/status") { return new Response(JSON.stringify({ status: "ok", @@ -310,26 +400,30 @@ const apiActor = actor({ headers: { "Content-Type": "application/json" } }); } - + // Return void to continue to default routing return; }, - + actions: { /* ... */ } }); ``` ### `onWebSocket` -The `onWebSocket` hook handles WebSocket connections to your actor. It receives the actor context, a `WebSocket` object, and the initial `Request`. Use this to set up WebSocket event listeners and handle real-time communication. +`onWebSocket(c: ActorContext, websocket: WebSocket): void | Promise` + +The `onWebSocket` hook handles WebSocket connections to your actor. Can be async. It receives the actor context and a `WebSocket` object. Use this to set up WebSocket event listeners and handle real-time communication. + +See [WebSocket Handler](/docs/actors/websocket-handler) for more details. ```typescript import { actor } from "rivetkit"; const realtimeActor = actor({ state: { connectionCount: 0 }, - - onWebSocket: (c, websocket, request) => { + + onWebSocket: (c, websocket) => { c.state.connectionCount++; // Send welcome message @@ -360,77 +454,18 @@ const realtimeActor = actor({ }); ``` -### `onAuth` - -The `onAuth` hook is called on the HTTP server before clients can interact with the actor. This hook is required for any public HTTP endpoint access and is used to validate client credentials and return authentication data that will be available on connections. - -This hook runs on the HTTP server (not the actor) to reduce load and prevent denial of service attacks against individual actors. Only called for public endpoints - calls to actors from within the backend do not trigger this handler. - -```typescript -import { actor } from "rivetkit"; - -const secureActor = actor({ - // Authentication handler - runs on HTTP server - onAuth: async (params: undefined, { request }) => { - const authHeader = request.headers.get("authorization"); - if (!authHeader?.startsWith("Bearer ")) { - throw new Error("Missing or invalid authorization header"); - } - - const token = authHeader.slice(7); - - // Validate token with your auth service - const user = await validateAuthToken(token); - if (!user) { - throw new Error("Invalid authentication token"); - } - - // Return auth data (must be serializable) - return { - userId: user.id, - role: user.role, - permissions: user.permissions - }; - }, - - state: { activeUsers: {} }, - - onConnect: (c) => { - // Access auth data from onAuth - const userId = c.conn.auth.userId; - const role = c.conn.auth.role; - - console.log(`User ${userId} with role ${role} connected`); - - c.state.activeUsers[userId] = { - role, - connectedAt: Date.now() - }; - }, - - actions: { - adminAction: (c) => { - // Check permissions from auth data - if (c.conn.auth.role !== "admin") { - throw new Error("Unauthorized: admin role required"); - } - - return { message: "Admin action completed" }; - } - } -}); -``` - ### `onBeforeActionResponse` -The `onBeforeActionResponse` hook is called before sending an action response to the client. Use this hook to modify or transform the output of an action before it's sent to the client. This is useful for formatting responses, adding metadata, or applying transformations to the output. +`onBeforeActionResponse(c: ActorContext, name: string, args: unknown[], output: TOutput): TOutput | Promise` + +The `onBeforeActionResponse` hook is called before sending an action response to the client. Can be async. Use this hook to modify or transform the output of an action before it's sent to the client. This is useful for formatting responses, adding metadata, or applying transformations to the output. ```typescript import { actor } from "rivetkit"; const loggingActor = actor({ state: { requestCount: 0 }, - + onBeforeActionResponse: (c, actionName, args, output) => { // Log action calls console.log(`Action ${actionName} called with args:`, args); @@ -471,9 +506,77 @@ const loggingActor = actor({ }); ``` -## Destroying Actors +## Options + +The `options` object allows you to configure various timeouts and behaviors for your actor. + +```typescript +import { actor } from "rivetkit"; + +const myActor = actor({ + state: { count: 0 }, + + options: { + // Timeout for createVars function (default: 5000ms) + createVarsTimeout: 5000, + + // Timeout for createConnState function (default: 5000ms) + createConnStateTimeout: 5000, + + // Timeout for onConnect hook (default: 5000ms) + onConnectTimeout: 5000, + + // Timeout for onSleep hook (default: 5000ms) + onSleepTimeout: 5000, -_Destroying actors is not available yet._ + // Timeout for onDestroy hook (default: 5000ms) + onDestroyTimeout: 5000, + + // Interval for saving state (default: 10000ms) + stateSaveInterval: 10_000, + + // Timeout for action execution (default: 60000ms) + actionTimeout: 60_000, + + // Max time to wait for background promises during shutdown (default: 15000ms) + waitUntilTimeout: 15_000, + + // Timeout for connection liveness check (default: 2500ms) + connectionLivenessTimeout: 2500, + + // Interval for connection liveness check (default: 5000ms) + connectionLivenessInterval: 5000, + + // Prevent actor from sleeping (default: false) + noSleep: false, + + // Time before actor sleeps due to inactivity (default: 30000ms) + sleepTimeout: 30_000, + + // Whether WebSockets can hibernate for onWebSocket (default: false) + // Can be a boolean or a function that takes a Request and returns a boolean + canHibernateWebSocket: false, + }, + + actions: { /* ... */ } +}); +``` + +| Option | Default | Description | +|--------|---------|-------------| +| `createVarsTimeout` | 5000ms | Timeout for `createVars` function | +| `createConnStateTimeout` | 5000ms | Timeout for `createConnState` function | +| `onConnectTimeout` | 5000ms | Timeout for `onConnect` hook | +| `onSleepTimeout` | 5000ms | Timeout for `onSleep` hook | +| `onDestroyTimeout` | 5000ms | Timeout for `onDestroy` hook | +| `stateSaveInterval` | 10000ms | Interval for persisting state | +| `actionTimeout` | 60000ms | Timeout for action execution | +| `waitUntilTimeout` | 15000ms | Max time to wait for background promises during shutdown | +| `connectionLivenessTimeout` | 2500ms | Timeout for connection liveness check | +| `connectionLivenessInterval` | 5000ms | Interval for connection liveness check | +| `noSleep` | false | Prevent actor from sleeping | +| `sleepTimeout` | 30000ms | Time before actor sleeps due to inactivity | +| `canHibernateWebSocket` | false | Whether WebSockets can hibernate (experimental) | ## Advanced @@ -525,7 +628,7 @@ const myActor = actor({ state: { count: 0 }, // Use external function in lifecycle hook - onStart: (c) => logActorStarted(c) + onWake: (c) => logActorStarted(c) }); // Simple external function with typed context @@ -539,103 +642,98 @@ See [Helper Types](/docs/actors/helper-types) for more details on using `ActorCo ## Full Example ```typescript -import { actor, ActorInitContext } from "rivetkit"; -import { z } from "zod"; +import { actor, InitContext } from "rivetkit"; interface CounterInput { - initialCount?: number; - stepSize?: number; - name?: string; + initialCount?: number; + stepSize?: number; + name?: string; +} + +interface CounterState { + count: number; + stepSize: number; + name: string; + requestCount: number; +} + +interface ConnParams { + userId: string; + role: string; +} + +interface ConnState { + userId: string; + role: string; + connectedAt: number; } const counter = actor({ - // Authentication handler (runs on HTTP server) - onAuth: async (opts) => { - const authHeader = opts.req.headers.get("authorization"); - if (!authHeader?.startsWith("Bearer ")) { - throw new Error("Missing authorization header"); - } - - const token = authHeader.slice(7); - const user = await validateAuthToken(token); - if (!user) { - throw new Error("Invalid auth token"); - } - - return { - userId: user.id, - role: user.role - }; - }, - // Initialize state with input - createState: (c: ActorInitContext, input: CounterInput) => ({ + createState: (c: InitContext, input: CounterInput): CounterState => ({ count: input.initialCount ?? 0, stepSize: input.stepSize ?? 1, name: input.name ?? "Unnamed Counter", requestCount: 0, }), - + // Initialize actor (run setup that doesn't affect initial state) - onCreate: (c, opts, input: { name: string }) => { + onCreate: (c, input: CounterInput) => { console.log(`Counter "${input.name}" initialized`); // Set up external resources, logging, etc. }, - - // Define default connection state - connState: { - role: "guest" - }, - - createConnState: (c, opts) => { - // Auth data is available from onAuth + + // Dynamically create connection state from params + createConnState: (c, params: ConnParams): ConnState => { return { - userId: c.conn.auth.userId, - role: c.conn.auth.role + userId: params.userId, + role: params.role, + connectedAt: Date.now() }; }, - + // Lifecycle hooks - onStart: (c) => { + onWake: (c) => { console.log(`Counter "${c.state.name}" started with count:`, c.state.count); }, - + onStateChange: (c, newState) => { - c.broadcast('countUpdated', { + c.broadcast('countUpdated', { count: newState.count, - name: newState.name + name: newState.name }); }, - - onBeforeConnect: (c, { params }) => { - // Additional validation can be done here if needed - // Auth was already validated in onAuth - console.log(`User ${c.conn.auth.userId} attempting to connect`); + + onBeforeConnect: (c, params: ConnParams) => { + // Validate connection params + if (!params.userId) { + throw new Error("userId is required"); + } + console.log(`User ${params.userId} attempting to connect`); }, - - onConnect: (c) => { - console.log(`User ${c.conn.state.userId} connected to "${c.state.name}"`); + + onConnect: (c, conn) => { + console.log(`User ${conn.state.userId} connected to "${c.state.name}"`); }, - - onDisconnect: (c) => { - console.log(`User ${c.conn.state.userId} disconnected from "${c.state.name}"`); + + onDisconnect: (c, conn) => { + console.log(`User ${conn.state.userId} disconnected from "${c.state.name}"`); }, - + // Transform all action responses onBeforeActionResponse: (c, actionName, args, output) => { c.state.requestCount++; - + return { data: output, metadata: { action: actionName, timestamp: Date.now(), - userId: c.conn.auth.userId, requestNumber: c.state.requestCount } }; }, - + // Define actions actions: { increment: (c, amount?: number) => { @@ -643,17 +741,7 @@ const counter = actor({ c.state.count += step; return c.state.count; }, - - reset: (c) => { - // Check if user has admin role - if (c.conn.auth.role !== "admin") { - throw new Error("Unauthorized: requires admin role"); - } - - c.state.count = 0; - return c.state.count; - }, - + getInfo: (c) => ({ name: c.state.name, count: c.state.count, diff --git a/website/src/content/docs/actors/quickstart/backend.mdx b/website/src/content/docs/actors/quickstart/backend.mdx index 8d326ffaf7..7c71cab336 100644 --- a/website/src/content/docs/actors/quickstart/backend.mdx +++ b/website/src/content/docs/actors/quickstart/backend.mdx @@ -197,7 +197,7 @@ import { createRivetKit } from "@rivetkit/react"; import { useState } from "react"; import type { registry } from "./registry"; -const { useActor } = createRivetKit("http://localhost:8080"); +const { useActor } = createRivetKit(); function Counter() { const [count, setCount] = useState(0); diff --git a/website/src/content/docs/actors/quickstart/cloudflare-workers.mdx b/website/src/content/docs/actors/quickstart/cloudflare-workers.mdx index aa0a25efb7..bbdb5c025d 100644 --- a/website/src/content/docs/actors/quickstart/cloudflare-workers.mdx +++ b/website/src/content/docs/actors/quickstart/cloudflare-workers.mdx @@ -44,6 +44,15 @@ Choose your preferred web framework: +```ts {{"title":"Default"}} +import { createHandler } from "@rivetkit/cloudflare-workers"; +import { registry } from "./registry"; + +// The `/rivet` endpoint is automatically exposed here for external clients +const { handler, ActorHandler } = createHandler(registry); +export { handler as default, ActorHandler }; +``` + ```ts {{"title":"Hono"}} import { createHandler, type Client } from "@rivetkit/cloudflare-workers"; import { Hono } from "hono"; @@ -62,6 +71,7 @@ app.post("/increment/:name", async (c) => { return c.json({ count: newCount }); }); +// The `/rivet` endpoint is automatically exposed here for external clients const { handler, ActorHandler } = createHandler(registry, { fetch: app.fetch }); export { handler as default, ActorHandler }; ``` @@ -70,6 +80,7 @@ export { handler as default, ActorHandler }; import { createHandler } from "@rivetkit/cloudflare-workers"; import { registry } from "./registry"; +// The `/rivet` endpoint is automatically mounted on this router for external clients const { handler, ActorHandler } = createHandler(registry, { fetch: async (request, env, ctx) => { const url = new URL(request.url); @@ -93,11 +104,48 @@ const { handler, ActorHandler } = createHandler(registry, { export { handler as default, ActorHandler }; ``` - +```ts {{"title":"Advanced"}} +import { createInlineClient } from "@rivetkit/cloudflare-workers"; +import { registry } from "./registry"; + +const { + client, + fetch: rivetFetch, + ActorHandler, +} = createInlineClient(registry); + +// IMPORTANT: Your Durable Object must be exported here +export { ActorHandler }; + +export default { + fetch: async (request, env, ctx) => { + const url = new URL(request.url); + + // Custom request handler + if (request.method === "POST" && url.pathname.startsWith("/increment/")) { + const name = url.pathname.slice("/increment/".length); - -The `/rivet` endpoint is automatically mounted by Rivet and is required for client communication. The Cloudflare Workers driver handles this automatically. This can be configured with `managerPath`. - + const counter = client.counter.getOrCreate(name); + const newCount = await counter.increment(1); + + return new Response(JSON.stringify({ count: newCount }), { + headers: { "Content-Type": "application/json" }, + }); + } + + // Optional: Mount /rivet path to access actors from external clients + if (url.pathname.startsWith("/rivet")) { + const strippedPath = url.pathname.substring("/rivet".length); + url.pathname = strippedPath; + const modifiedRequest = new Request(url.toString(), request); + return rivetFetch(modifiedRequest, env, ctx); + } + + return new Response("Not Found", { status: 404 }); + }, +} satisfies ExportedHandler; +``` + @@ -179,7 +227,7 @@ wrangler deploy Your actors will now run on Cloudflare's edge with persistent state backed by Durable Objects. -See the [Cloudflare Workers deployment guide](/docs/deploy/cloudflare-workers) for detailed deployment instructions and configuration options. +See the [Cloudflare Workers deployment guide](/docs/connect/cloudflare-workers) for detailed deployment instructions and configuration options. diff --git a/website/src/content/docs/actors/quickstart/next-js.mdx b/website/src/content/docs/actors/quickstart/next-js.mdx index ce3ff57589..734516c65e 100644 --- a/website/src/content/docs/actors/quickstart/next-js.mdx +++ b/website/src/content/docs/actors/quickstart/next-js.mdx @@ -107,7 +107,7 @@ For more examples on connecting to your actors using React, check the [React doc -See the [Vercel deployment guide](/docs/deploy/vercel) for detailed instructions on deploying your RivetKit app to Vercel. +See the [Vercel deployment guide](/docs/connect/vercel) for detailed instructions on deploying your RivetKit app to Vercel. diff --git a/website/src/content/docs/actors/quickstart/react.mdx b/website/src/content/docs/actors/quickstart/react.mdx index c2a3b7492c..9bc6a8e94d 100644 --- a/website/src/content/docs/actors/quickstart/react.mdx +++ b/website/src/content/docs/actors/quickstart/react.mdx @@ -56,12 +56,11 @@ registry.start(); Set up your React application: ```tsx {{"title":"frontend/App.tsx"}} -import { createClient, createRivetKit } from "@rivetkit/react"; +import { createRivetKit } from "@rivetkit/react"; import { useState } from "react"; import type { registry } from "../backend/registry"; -const client = createClient(); -const { useActor } = createRivetKit(client); +const { useActor } = createRivetKit(); function App() { const [count, setCount] = useState(0); diff --git a/website/src/content/docs/actors/request-handler.mdx b/website/src/content/docs/actors/request-handler.mdx new file mode 100644 index 0000000000..31ea6b1b9b --- /dev/null +++ b/website/src/content/docs/actors/request-handler.mdx @@ -0,0 +1,176 @@ +# Low-Level HTTP Request Handler + +Actors can handle HTTP requests through the `onRequest` handler. + +For most use cases, [actions](/docs/actors/actions) provide high-level API powered by HTTP that's easier to work with than low-level HTTP. However, low-level handlers are required when implementing custom use cases or integrating external libraries that need direct access to the underlying HTTP `Request`/`Response` objects or WebSocket connections. + +## Handling HTTP Requests + +The `onRequest` handler processes HTTP requests sent to your actor. It receives the actor context and a standard `Request` object and returns a `Response` object. + + + + +```typescript +import { actor } from "rivetkit"; + +export const counterActor = actor({ + state: { + count: 0, + }, + // WinterTC compliant - accepts standard Request and returns standard Response + onRequest: (c, request) { + const url = new URL(request.url); + + if (request.method === "GET" && url.pathname === "/count") { + return Response.json({ count: c.state.count }); + } + + if (request.method === "POST" && url.pathname === "/increment") { + c.state.count++; + return Response.json({ count: c.state.count }); + } + + return new Response("Not Found", { status: 404 }); + }, +}); +``` + + + + +```typescript +import { type ActorContext, actor } from "rivetkit"; +import { Hono } from "hono"; + +function buildRouter(c: ActorContext<{ count: number }>) { + const app = new Hono(); + + app.get("/count", (c) => { + return c.json({ count: c.state.count }); + }); + + app.post("/increment", (c) => { + c.state.count++; + return c.json({ count: c.state.count }); + }); + + return app; +} + +export const counterActor = actor({ + state: { + count: 0, + }, + createVars: (c) => { + const app = buildRouter(c); + return { app }; + }, + async onRequest: (c, request) { + return await c.vars.app.fetch(request); + }, +}); +``` + + + + +See also the [raw fetch handler example](https://github.com/rivet-dev/rivetkit/tree/main/examples/raw-fetch-handler). + +## Sending Requests To Actors + +### Via RivetKit Client + +Use the `.fetch()` method on an actor handle to send HTTP requests to the actor's `onRequest` handler. This can be executed from either your frontend or backend. + +```typescript +import { createClient } from "rivetkit/client"; + +const client = createClient(); + +const actor = client.counter.getOrCreate("my-counter"); + +// .fetch() is WinterTC compliant, it accepts standard Request and returns standard Response +const response = await actor.fetch("/increment", { method: "POST" }); +const data = await response.json(); +console.log(data); // { count: 1 } +``` + +### Via HTTP API + +This handler can be accessed with raw HTTP using `https://api.rivet.dev/gateway/{actorId}/request/{...path}`. + +For example, to call `POST /increment` on the counter actor above: + + + +```typescript +const response = await fetch( + `https://api.rivet.dev/gateway/${actorId}/request/increment`, + { + method: "POST", + headers: { + Authorization: `Bearer ${token}`, + }, + } +); +const data = await response.json(); +console.log(data); // { count: 1 } +``` + +```bash +curl -X POST "https://api.rivet.dev/gateway/{actorId}/request/increment" \ + -H "Authorization: Bearer {token}" +``` + + + +The request is routed to the actor's `onRequest` handler where: + +- `request.method` is `"POST"` +- `request.url` ends with `/increment` (the path after `/request/`) +- Headers, body, and other request properties are passed through unchanged + +See the [HTTP API reference](/docs/actors/http-api) for more information on HTTP routing and authentication. + +### Via Proxying Requests + +You can proxy HTTP requests from your own server to actor handlers using the RivetKit client. This is useful when you need to add custom authentication, rate limiting, or request transformation before forwarding to actors. + +```typescript +import { Hono } from "hono"; +import { createClient } from "rivetkit/client"; +import { serve } from "@hono/node-server"; + +const client = createClient(); + +const app = new Hono(); + +// Proxy requests to actor's onRequest handler +app.all("/actors/:id/:path{.*}", async (c) => { + const actorId = c.req.param("id"); + const actorPath = (c.req.param("path") || ""); + + // Forward to actor's onRequest handler + const actor = client.counter.get(actorId); + return await actor.fetch(actorPath, c.req.raw); +}); + +serve(app); +``` + +## Connection & Lifecycle Hooks + +`onRequest` will trigger the `onBeforeConnect`, `onConnect`, and `onDisconnect` hooks. Read more about [lifecycle hooks](/docs/actors/lifecycle). + +Requests in flight will be listed in `c.conns`. Read more about [connections](/docs/actors/connections). + +## WinterTC Compliance + +The `onRequest` handler is WinterTC compliant and will work with existing libraries using the standard `Request` and `Response` types. + +## Limitations + +- Does not support streaming responses & server-sent events at the moment. See the [tracking issue](https://github.com/rivet-dev/rivet/issues/3529). +- `OPTIONS` requests currently are handled by Rivet and are not passed to `onRequest` + diff --git a/website/src/content/docs/actors/scaling.mdx b/website/src/content/docs/actors/scaling.mdx index 5d5b3911c8..24a2824535 100644 --- a/website/src/content/docs/actors/scaling.mdx +++ b/website/src/content/docs/actors/scaling.mdx @@ -1,48 +1,4 @@ # Scaling & Concurrency -This document covers how actors are able to scale better than traditional applications & provides tips on architecting your actors. +This page has moved to [design patterns](/docs/actors/design-patterns). -## How actors scale - -Actors scale by design through these key properties: - -| Property | Description | -| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **Independent State** | Each actor manages its own private data separately from other actors, so they never conflict with each other when running at the same time (i.e. using locking mechanisms). | -| **Action- & Event-Based Communication** | Actors communicate through asynchronous [actions](/docs/actors/actions) or [events](/docs/actors/events), making it easy to distribute them across different machines. | -| **Location Transparency** | Unlike traditional servers, actors don't need to know which machine other actors are running on in order to communicate with each other. They can run on the same machine, across a network, and across the world. Actors handle the network routing for you under the hood. | -| **Horizontal Scaling** | Actors distribute workload by splitting responsibilities into small, focused units. Since each actor handles a limited scope (like a single user, document, or chat room), the system automatically spreads load across many independent actors rather than concentrating it in a single place. | - -## Tips for architecting actors for scale - -Here are key principles for architecting your actor system: - -**Single Responsibility** - -- Each actor should represent one specific entity or concept from your application (e.g., `User`, `Document`, `ChatRoom`). -- This makes your system scale better, since actors have small scopes and do not conflict with each other. - -**State Management** - -- Each actor owns and manages only its own state -- Use [actions](/docs/actors/actions) to request data from other actors -- Keep state minimal and relevant to the actor's core responsibility - -**Granularity Guidelines** - -- Too coarse: Actors handling too many responsibilities become bottlenecks -- Too fine: Excessive actors create unnecessary communication overhead -- Aim for actors that can operate independently with minimal cross-actor communication - -### Examples - -**Good actor boundaries** - -- `User`: Manages user profile, preferences, and authentication -- `Document`: Handles document content, metadata, and versioning -- `ChatRoom`: Manages participants and message history - -**Poor actor boundaries** - -- `Application`: Too broad, handles everything -- `DocumentWordCount`: Too granular, should be part of DocumentActor diff --git a/website/src/content/docs/actors/sharing-and-joining-state.mdx b/website/src/content/docs/actors/sharing-and-joining-state.mdx index 213710dc5c..f941b56c16 100644 --- a/website/src/content/docs/actors/sharing-and-joining-state.mdx +++ b/website/src/content/docs/actors/sharing-and-joining-state.mdx @@ -1,29 +1,4 @@ # Sharing and Joining State -Actors store data separately by design, so combining data from multiple actors works differently than traditional databases. This pattern is similar to patterns you'll see in distributed like Cassandra, DynamoDB, and ClickHouse. +This page has moved to [design patterns](/docs/actors/design-patterns). -Here are your options based on your needs: - -## Few actors, need latest data - -- Call actions on each actor to get their data -- Actions are fast, so this works well for small numbers of actors -- Trade-off: More work when reading data, but writing is simple - -## Many actors, need latest data - -- Have actors automatically send updates to other actors that need them -- This keeps everyone in sync without extra calls -- Trade-off: More work when data changes, but reading is fast - -## Many actors, okay with slightly old data - -- Write data to a separate OLAP database like ClickHouse when updating state -- Query the analytics database for fast joins -- Trade-off: Extra database to maintain, but great performance - -## Many actors, need latest data (not recommended) - -- Write data to a transactional OLTP database like Postgres or MySQL when updating state -- This works but adds complexity you usually don't need -- Trade-off: Heavy database overhead for minimal benefit diff --git a/website/src/content/docs/actors/websocket-handler.mdx b/website/src/content/docs/actors/websocket-handler.mdx new file mode 100644 index 0000000000..6989ccc2b8 --- /dev/null +++ b/website/src/content/docs/actors/websocket-handler.mdx @@ -0,0 +1,217 @@ +# Low-Level WebSocket Handler + +Actors can handle WebSocket connections through the `onWebSocket` handler. + +For most use cases, [actions](/docs/actors/actions) and [events](/docs/actors/events) provide high-level connection handling powered by WebSockets that's easier to work with than low-level WebSockets. However, low-level handlers are required when implementing custom use cases. + +## Handling WebSocket Connections + +The `onWebSocket` handler manages low-level WebSocket connections. It receives the actor context and a `WebSocket` object. + +```typescript +import { actor } from "rivetkit"; + +export const chatActor = actor({ + state: { messages: [] as string[] }, + onWebSocket: (c, websocket) { + websocket.addEventListener("open", () => { + // Send existing messages to new connection + websocket.send(JSON.stringify({ + type: "history", + messages: c.state.messages, + })); + }); + + websocket.addEventListener("message", (event) => { + // Store message + c.state.messages.push(event.data); + + // Echo message back + websocket.send(event.data); + + // Manually save state since WebSocket connections are long-lived + c.saveState(); + }); + }, +}); +``` + +See also the [raw WebSocket handler example](https://github.com/rivet-dev/rivetkit/tree/main/examples/raw-websocket-handler). + +## Connecting To Actors + +### Via RivetKit Client + +Use the `.websocket()` method on an actor handle to open a WebSocket connection to the actor's `onWebSocket` handler. This can be executed from either your frontend or backend. + +```typescript +import { createClient } from "rivetkit/client"; + +const client = createClient(); + +const actor = client.chat.getOrCreate("my-chat"); + +// Open WebSocket connection +const ws = await actor.websocket("/"); + +// Listen for messages +ws.addEventListener("message", (event) => { + const message = JSON.parse(event.data); + console.log("Received:", message); +}); + +// Send messages +ws.send(JSON.stringify({ type: "chat", text: "Hello!" })); +``` + +The `.websocket()` method returns a standard WebSocket. + +### Via HTTP API + +This handler can be accessed with raw WebSockets using `wss://api.rivet.dev/gateway/{actorId}@{token}/websocket/{...path}`. + +For example, to connect to the chat actor above: + + + +```typescript +const ws = new WebSocket( + `wss://api.rivet.dev/gateway/${actorId}@${token}/websocket/` +); + +ws.addEventListener("message", (event) => { + const message = JSON.parse(event.data); + console.log("Received:", message); +}); + +ws.addEventListener("open", () => { + ws.send(JSON.stringify({ type: "chat", text: "Hello!" })); +}); +``` + +```bash +wscat -c "wss://api.rivet.dev/gateway/{actorId}@{token}/websocket/" +``` + + + +The path after `/websocket/` is passed to your `onWebSocket` handler and can be used to route to different functionality within your actor. For example, to connect with a custom path `/admin`: + + + +```typescript +const ws = new WebSocket( + `wss://api.rivet.dev/gateway/${actorId}@${token}/websocket/admin` +); +``` + +```bash +wscat -c "wss://api.rivet.dev/gateway/{actorId}@{token}/websocket/admin" +``` + + + +See the [HTTP API reference](/docs/actors/http-api) for more information on WebSocket routing and authentication. + +### Via Proxying Connections + +You can proxy WebSocket connections from your own server to actor handlers using the RivetKit client. This is useful when you need to add custom authentication or connection management before forwarding to actors. + +```typescript +import { Hono } from "hono"; +import { upgradeWebSocket } from "hono/cloudflare-workers"; +import { createClient } from "rivetkit/client"; + +const client = createClient(); + +const app = new Hono(); + +// Proxy WebSocket connections to actor's onWebSocket handler +app.get("/ws/:id", upgradeWebSocket(async (c) => { + const actorId = c.req.param("id"); + const actor = client.chat.get(actorId); + const actorWs = await actor.websocket("/"); + + return { + onOpen: (evt, ws) => { + actorWs.addEventListener("message", (event) => { + ws.send(event.data); + }); + actorWs.addEventListener("close", () => { + ws.close(); + }); + }, + onMessage: (evt, ws) => { + actorWs.send(evt.data); + }, + onClose: () => { + actorWs.close(); + }, + }; +})); + +export default app; +``` + +See also the [raw WebSocket handler with proxy example](https://github.com/rivet-dev/rivetkit/tree/main/examples/raw-websocket-handler-proxy). + +## Connection & Lifecycle Hooks + +`onWebSocket` will trigger the `onBeforeConnect`, `onConnect`, and `onDisconnect` hooks. Read more about [lifecycle hooks](/docs/actors/lifecycle). + +Open WebSockets will be listed in `c.conns`. `conn.send` and `c.broadcast` have no effect on low-level WebSocket connections. Read more about [connections](/docs/actors/connections). + +## WinterTC Compliance + +The `onWebSocket` handler uses standard WebSocket APIs and will work with existing libraries expecting WinterTC-compliant WebSocket objects. + +## Advanced + +## WebSocket Hibernation + +WebSocket hibernation allows actors to go to sleep while keeping WebSocket connections alive. Actors automatically wake up when a message is received or the connection closes. + +Enable hibernation by setting `canHibernateWebSocket: true`. You can also pass a function `(request) => boolean` for conditional control. + +```typescript +export const myActor = actor({ + // ... + options: { + canHibernateWebSocket: true, + }, +}); +``` + +Since `open` only fires once when the client first connects, use `c.conn.state` to store per-connection data that persists across sleep cycles. See [connections](/docs/actors/connections) for more details. + +### Accessing the Request + +The underlying HTTP request is available via `c.request`. This is useful for accessing the path or query parameters. + +```typescript +onWebSocket: (c, websocket) { + const url = new URL(c.request.url); + console.log(url.pathname); // e.g., "/admin" + console.log(url.searchParams.get("foo")); // e.g., "bar" +} +``` + +### Async Handlers + +The `onWebSocket` handler can be async, allowing you to perform async code before setting up event listeners: + +```typescript +onWebSocket: async (c, websocket) => { + // Perform async operations before the connection is ready + const metadata = await fetch("https://api.example.com/metadata").then(r => r.json()); + + websocket.addEventListener("open", () => { + // Send metadata on connection + websocket.send(JSON.stringify({ metadata })); + }); + + websocket.addEventListener("message", (event) => { + // Handle messages + }); +} +``` diff --git a/website/src/content/docs/clients/openapi.mdx b/website/src/content/docs/clients/openapi.mdx deleted file mode 100644 index 21e25d4295..0000000000 --- a/website/src/content/docs/clients/openapi.mdx +++ /dev/null @@ -1,6 +0,0 @@ -# OpenAPI - -The Rivet OpenAPI spec is available [here](https://github.com/rivet-dev/rivetkit/blob/main/clients/openapi/openapi.json) - -The OpenAPI spec currently only exposes creating & managing actors. It does not expose how to communicate with actors. See the [HTTP client implementation](https://github.com/rivet-dev/rivetkit/blob/b5072fdac18d90a27bb6cd36e9ee73b00d36d42c/packages/rivetkit/src/client/actor-handle.ts) for reference. - diff --git a/website/src/content/docs/clients/react.mdx b/website/src/content/docs/clients/react.mdx index 4f8fbd9dba..79e5dec336 100644 --- a/website/src/content/docs/clients/react.mdx +++ b/website/src/content/docs/clients/react.mdx @@ -10,21 +10,20 @@ See the [React quickstart guide](/docs/actors/quickstart/react) for getting star ## API Reference -### `createRivetKit(client, options?)` +### `createRivetKit(endpoint?, options?)` Creates the Rivet hooks for React integration. ```tsx -import { createClient, createRivetKit } from "@rivetkit/react"; +import { createRivetKit } from "@rivetkit/react"; import type { registry } from "./backend/registry"; -const client = createClient(); -const { useActor } = createRivetKit(client); +const { useActor } = createRivetKit(); ``` #### Parameters -- `client`: The Rivet client created with `createClient` +- `endpoint`: Optional endpoint URL (defaults to `http://localhost:6420` or `process.env.RIVET_ENDPOINT`) - `options`: Optional configuration object #### Returns diff --git a/website/src/content/docs/connect/cloudflare-workers.mdx b/website/src/content/docs/connect/cloudflare-workers.mdx index 0d9cc61df0..5085388f41 100644 --- a/website/src/content/docs/connect/cloudflare-workers.mdx +++ b/website/src/content/docs/connect/cloudflare-workers.mdx @@ -5,8 +5,14 @@ import { faGithub } from "@rivet-gg/icons"; Deploy your Cloudflare Workers + RivetKit app to [Cloudflare Workers](https://workers.cloudflare.com/). - -Complete example Cloudflare Workers + RivetKit app. + +Minimal Cloudflare Workers + RivetKit example. + + +Cloudflare Workers with Hono router. + + +Advanced setup using createInlineClient. @@ -17,7 +23,6 @@ Complete example Cloudflare Workers + RivetKit app. - [Cloudflare account](https://dash.cloudflare.com/) with Durable Objects enabled - [Wrangler CLI](https://developers.cloudflare.com/workers/wrangler/install-and-update/) v3 -- Access to the [Rivet Cloud](https://dashboard.rivet.dev/) or a self-hosted [Rivet Engine](/docs/general/self-hosting) - A Cloudflare Worker app integrated with RivetKit - See the [Cloudflare Workers quickstart](/docs/actors/quickstart/cloudflare-workers/) or [Cloudflare Workers example](https://github.com/rivet-dev/rivetkit/tree/main/examples/cloudflare-workers) to get started diff --git a/website/src/content/docs/connect/hetzner.mdx b/website/src/content/docs/connect/hetzner.mdx index 4478eb4e6f..c7f34aaa67 100644 --- a/website/src/content/docs/connect/hetzner.mdx +++ b/website/src/content/docs/connect/hetzner.mdx @@ -1,4 +1,4 @@ # Deploying to Hetzner -Please see the [VM & Bare Metal](/docs/deploy/vm-and-bare-metal) guide. +Please see the [VM & Bare Metal](/docs/connect/vm-and-bare-metal) guide. diff --git a/website/src/content/docs/drivers/file-system.mdx b/website/src/content/docs/drivers/file-system.mdx index adf2b65fd8..bcccaf5bad 100644 --- a/website/src/content/docs/drivers/file-system.mdx +++ b/website/src/content/docs/drivers/file-system.mdx @@ -12,7 +12,6 @@ The File System driver is ideal for development and single-node deployments. For | --- | --- | | Horizontal scaling | No | | WebSockets | Yes | -| SSE | Yes | | Edge | No | | Scheduling | Yes | diff --git a/website/src/content/docs/drivers/memory.mdx b/website/src/content/docs/drivers/memory.mdx index a20b473b5a..26307c8fcd 100644 --- a/website/src/content/docs/drivers/memory.mdx +++ b/website/src/content/docs/drivers/memory.mdx @@ -12,7 +12,6 @@ The Memory driver does not persist data between server restarts. For production | --- | --- | | Horizontal scaling | No | | WebSockets | Yes | -| SSE | Yes | | Edge | No | | Scheduling | Yes | diff --git a/website/src/content/docs/general/architecture.mdx b/website/src/content/docs/general/architecture.mdx index 508fc238b8..7c78a5aa01 100644 --- a/website/src/content/docs/general/architecture.mdx +++ b/website/src/content/docs/general/architecture.mdx @@ -1,47 +1,447 @@ # Architecture -Rivet supports three topologies that define how actors are distributed and scale. +## 3 ways of running - - Each platform configures a default topology appropriate for that environment. In most cases, you can rely on these defaults unless you have specific distribution needs. - +### rivetkit -## Configuration +- rivetkit is the typescript library used for both local development & to connect your application to rivet +- a rivetkit instance is called a "runner." you can run multiple runners to scale rivetkit horiziotnally. read omre about runners below. -```typescript -const config = { - topology: "standalone" // or "partition" or "coordinate" -}; -``` +#### local development -## Types of Topologies +- in local development, rivetkit provides a full actor environment for single-node deployments -### Standalone +#### drivers -- **How it works**: Runs all actors in a single process -- **When to use**: Development, testing, simple apps with low traffic -- **Limitations**: No horizontal scaling, single point of failure -- **Default on**: Node.js, Bun +- rivetkit supports multiple drivers. currently supports: file system (default in local dev), memory, rivet engine (used for rivet cloud & self-hosting), cloudflare durable objects (does not rely on rivet engine) +- drivers are very flexible to enable you to write your actors once and plug in to any system that fits your architecture adequately +- see the driver interface + - actordriver https://github.com/rivet-dev/rivet/blob/eeb01fc4d9ca0e06f2e740d267bd53280ca7330e/rivetkit-typescript/packages/rivetkit/src/actor/driver.ts + - managerdriver https://github.com/rivet-dev/rivet/blob/eeb01fc4d9ca0e06f2e740d267bd53280ca7330e/rivetkit-typescript/packages/rivetkit/src/manager/driver.ts -### Partition +### rivet cloud -- **How it works**: Each actor has its own isolated process. Clients connect directly to the actor for optimal performance. -- **When to use**: Production environments needing horizontal scaling -- **Limitations**: Minimal - balanced performance and availability for most use cases -- **Default on**: Rivet, Cloudflare Workers +- provides multi-region and highest performance out of the box +- accessible at dashboard.rivet.dev and the api is avialble at api.rivet.dev -### Coordinate +### rivet self-hosted -- **How it works**: Creates a peer-to-peer network between multiple servers with leader election with multiple actors running on each server. Clients connect to any server and data is transmitted to the leader over a pubsub server. -- **When to use**: High-availability scenarios needing redundancy and failover -- **Limitations**: Added complexity, performance overhead, requires external data source -- **Default on**: _None_ +- available as a standalone rust binary or a docker contianer +- can be configured ot persist to postgres or rocksdb +- can scale horiziontally across multipe nodes and can scale across multiple regions +- see self-hosting docs (link to docs) -## Choosing a Topology +## actors -In most cases, use your platform's default: +- Actors for long-lived processes with durable state, realtime, and hibernate when not in use. read more about actors at a high level at (link to actors/index) + +### actor-per-entity + +- actors are designed to have an actor-per-entity +- you can think about actors a bit like objects in object-oriented programming where ach is responsible for their own state and expose methods (ie actions in our case) +- examples incldue + - actor per user + - actor per user session + - actor per document + - actor per game room + - actor per tenant + - actor per rate limit topic + +### architecting for scale + +- actors scale by: + - having isolated state to each acotr that combines compute and storage for in-memory reads and writes + - communication is stndardized based on actions & events + - scale horizontally +- read more about scalign at (link to scaling doc) + +### horizontal scaling + +- actors can run across multiple rivetkit runners. this is orchestrated by rivetkit itself. + +### lifecycle + +actors have create, destroy, wake, and sleep lifecycle hooks that you can implement to modify behavior. see the lifecycle docs for reference on actor lifecycel hook sequences + +### actor sleeping + +- actors sleep when not in use +- an actor is considered not in use when there are no active network connections to the actor (or the network connections are hibernatable websockets, see below) and there are no actions in flight +- actors have a sleep timeout (configured in options.onSleepTimeout) that decides how long to keep the actor in memory with no recent actions +- sleep can be disabled with `options.noSleep` + +### wake events + +- actors can wake to any of the follwoing events: + - network requests + - websocket messages + - alarms (see scheduling docs) + +### live actor migration + +- live actor migrations lets your application ugprade, crash, or hot reload cahnges without interruption to your user or application (including websockets) +- this is powered by hibernating websockets for live websocket migraiton & our fault tolerance mechanism (read more below) + +### coldstart performance + +- actors have negligible coldstart performance. the code to run the actor is already started (ie the runner), so creating/starting an actor is incredibly cheap. +- creating new actors with a key requires some overhead to communicate with other regions in order to reserve the actor's key (see below). actors can be created without keys with near-0 latency. + +### multi-region, globally unique actor keys + +- acotrs can optionally have a globally unique "key" +- when creating an actor with a key +- this system is highly optimized to reduce wan round trips using a process call EPaxos with a custom database called Epoxy (link to https://github.com/rivet-dev/rivet/tree/main/engine/packages/epoxy) +- limitation: when creating an actor with a given key, that key will always be pinned to that region even if the actor is destroyed. creating a new actor with the same key will always live in the same region. +- see the acotr keys document + +### input + +- actors have input data that can be passed to them when constructed +- this is similar to apssing data to a constructor in an object + +### generic parameters + +actor definitions include the following generic parameters that you'll see frequently in the code: + +- state +- conn state +- conn params +- ephemeral variables +- input data +- (experimental) database connector + +### persistence + +- state automatically flushes to storage intelligently +- to force a state flush and wait for it to finish, call (TODO: look this up in state document) +- read more about state persistence in the state document (link to document) +- state is stored in the same place as where the actor lives. loading an actor in to memory has comparable performance to network attached storage, and once in memory, has performance of any standard in-memory read/write like a variable. + +### scheduling & alarms + +- actors have a scheduling api to be able to wake up at any time in the indefinite future +- think of this like setTimeout but without a max timeout +- rivet is responsible for waking the actor when this timeout wakes + +### ephemeral variables + +- actors have the ability to create ephemrla variables for things that you do not want to be persisted with the actor's state +- this is useful for non-serializable data like a utility class like a pubsubs erver or something (TODO extra info) +- link to ephemeral variables docs + +### actions + +- for stateless clients, actions are sent as http requests via `POST /gateway/{actor id}/actions/{action name}` +- for stateful clients, actions are sent as websocket messages + +### events & subscriptions + +- events are sent as websocket messages + +### error handling + +- this is different than fault tolerance: + - error handling is a user error + - fault tolerance is something goes wrong that your applciation was not built to handle (ie hard crash, oom, network error) +- rivet provdies a special UserError class to throw custom errors that will be returned to the client +- all other errors are returned as a generic "internal error" +- this is becuase leaking error deatils is a common security hole, so we default to expose-nothing errors + +### logging + +- rivet uses pino for logging +- we expose a scoped child logger for each actor at `c.log` that automatically logs the actor id + key +- this allows you to search lgos easily by actor id without having to log the actor id frequently +- logs can be configured via the `LOG_LEVEL` env var + +### fault tolerance + +- actors are fault tolerant, meaning that the host machine can crash and the actors will proceed to operate as if nothing happened +- runners maintain a socket with rivet engine. when this socket closes or takes to long to ping, actors will reschedule +- hibernating websockets (enabled by default) will live-migrate to the new actor as if nothing happened + +### crash policy + +- there are 3 crash policies: sleep, restart, and destroyed + - sleep (default, usually the option you want): + - when to use: actors that need high-performance in-memory logic. + - when not to use: you need this actor running at all times no matter what, even if idle + - examples: (list commone xamples) + - destroy: + - when to use: actors that need to run once until completion. on crash, do not try to reschedule. + - when not to use: if you want your actor to have fault tolerance and be able to run transaprenlty to the underlying runner + - examples: batch jobs, image conversions, ephemeral jobs, (TODO come up with better eaxmples) + - restart: + - when to use: actors that should be running at all times + - when not to use: if you don't absolutely need something running at all times, since this consumes needless compute resources. considure using the scheduling api instead. + - examples: maintain outbound sockets, daemons, always-running jobs, (TODO come up with better examples) + +the behavior for each is described below: + +| Event | Restart | Sleep | Destroy | +|------------------------------|--------------|--------------|--------------| +| Graceful exit (StopCode::Ok) | Destroy | Destroy | Destroy | +| Crash (non-Ok exit) | Reschedule | Sleep | Destroy | +| Lost (runner disappeared) | Reschedule | Sleep | Destroy | +| Lost + force_reschedule | Reschedule | Reschedule | Reschedule | +| GoingAway (runner draining) | Reschedule | Sleep | Destroy | +| No capacity (allocation) | Queue (wait) | Sleep | Queue (wait) | +| No capacity + serverless | Queue (wait) | Queue (wait) | Queue (wait) | +| Wake signal (while sleeping) | Reschedule | Reschedule | Reschedule | + +### inspector + +- actors provide an inspector api to implement the: + - repl + - state read/write + - network inspector + - event log +- this is impelmented over a websocket over bare + +### http api + +- see the http api document on actors + +### multi-region + +- actors can be scheduled across multiple regions +- each actor has an actor id which embeds which region it lives in +- networking is automatically routed to the region that an actor lives in +- limitation: actors curretnly cannot migrate across regions + +### backpressure + +#### no runner capacity + +- this is how actors with different crash policies behave when when there's backpressure: + - sleep = sleeps (sheds load by not rescheduling) + - restart = queues + - destroy = queues +- see the above matrix for more details on actor crash policy on how it handles no capacity. + +- the actor queue is built to withstand high amounts of backpressure on rivet, so queueing actors is fine here +- a large queue means it'll take more time for your application to process the queue to catch up with demand when it comes online. + +#### per-actor cpu & networking exhaustion + +- actors are isolated, so they each have their own individual bottleneck. you can think of this like a process thread where each thread can only do so much. +- there is no durable message queue/"mailbox" for actors. if the actor cannot respond in time, then the request is dropped. +- if an actor exhauses its cpu or networking, then the runner +- returns service unavailble (503) if the actor fails to respond to a request in time +- there is no hard cap on the networking or cpu usage for each actor at the moment +- if your actor is resource intensive, it's common to use a separate mailbox actor to act as a queue + +## runners + +### regular vs serverless runners + +there are 2 types of runners: + +- regular: these are standard nodejs processes connected to rivet that rivet can orchestrate actors to and send network requests to at any time +- serverless: rivet works with serverless platforms. when an actor is created, it has a request-per-actor model where it opens a long-running request on the serverless platofrm to run a given actor. + +### runner pool + +- runners are pooled together by sharing a common name (ie "default") +- when an acotr is created, it chooses the pool by selecting the runner name to run on +- rivet will automatically load balance actors across these runners + +### runner key + +- not relevnat for serverless runners +- each runner has a unique key that it provides when connecting. keys are unique to the instace the runner is running on and should be the same if the runner is restarted. +- this can be the: machine's ip, k8s pod name, etc +- if there is an existing runner connected with a given key, the runner will disconnect the old runner and replace it +- rivet is designed to handle network partitions by waiting for runners to miss a ping, indicating it's no longer alive. however, often times runners restart immediately after a hard crash and reconnect. in this case, the runner will reconnect on restart and terminate the old runner in order to prevent further actors from scheduling to the crashed runner. + +### capacity + +- not relevnat for serverless runners +- each runner can be assigned a capacity of how many actors it can run +- rivet will schedule with spread (not binpacking) in order to spread load over actors + +#### usefulness of capacity = 1 + +- setting a capacity of 1 is helpful for situations where you have cpu-intensive apps that should not run with any other actors +- examples include game servers, ffmpeg jobs, etc + +### versions & upgrading code + +- each runner has a version index +- actors are always scheduled to the highest verison index (see runner priority below) +- this means that when a new runner is deployed: + 1. runners with higher index come online + 2. actors schedule to the highest index, stop scheduling to the older index + 3. old index runners start draining and migrating actors to new index + 4. all old runners are now shut down +- websocekts are live migrated to the new version when upgrading using hibernating websockets to users see no hiccup in their applications +- this is important because actors should never downgrade their runner. they should always move to a newer version of code in order to prevent corruption. + +### runner scheduling prioroty + +- actors are scheduled to runners sorted by priority of (version DESC, remaining capacity ASC) + +### multi-region + +TODO + +### shutdown sequence + +- runner shutdown is important to ensure that actors do not get unexpectedly terminated when either: + - upgrading your applciation and taking down old pods + - scaling down your runners horizontally (ie from an hpa) + - pressing ctrl-c when in development +- on shutdown: + 1. tell rivet the runner is stopping + 2. rivet tells all the actors on this runner to migrate + 3. runner waits for all actors to finish migrating + 4. runner exits process + +### reconnection + +- runners can handle temporary network partitions +- they'll automatically reconnect and replay missed commands/events between rivet and the runner +- this happens transparenlty to the user +- if disconnected for too long (indicating a network partition), the runner will shut itself down and exit + +### autoscaling + +- not relevant to serverless +- runners currently autoscale on cpu. more intelligent scaling is coming soon. +- tune your runner total slots capacity accordingly +- it's up to you to configure your hpa/etc to work like this. see the Connect guides (link to index page) for reference on hwo to configure this. + +### serverless timeouts + +- serverless runners take in to account the maximum run duration of the serverless platform +- the runners will mgirate actors to a new request before the request times out +- this is completely transparent to you and the user because of the fault tolerance and websocket migraiton characteristics +- it's common for actors to go sleep before hitting the serverless timeout + + +## networking + +### web standards + +- everything in rivet is built on webstandards by default +- nothing in rivet requires you to use our sdk, our sdks are meant to be a convenience. it's built to be as easy to use raw http/websocket endpoints from scratch. +- actions, events, etc are all built on simple, well-documented http/websocket under the hood (link to openapi & asyncapi docs). +- you can use low-level request handlers (lnk to dock) and low-level weboscket handlers (link to doc) to handle low-level primtivies yourself + +### encoding + +- rivetkit's action/events api supports communicating via [VBARE](link to github repo, see the blog post for the link), CBOR, or JSON + - VBARE: high-perofrmance & compact, optimal use case + - CBOR: descent encoding/decoding perf + portable libraries, good for implemnting high-ish performance on other platforms + - JSON: good for fast implementations & debugging (easy to read) + +### tunneling + +- when a runner connects it opens a tunnel to rivet to allow incoming traffic + - this is simila to systems like tailscale, ngrok, or other vpns + - we do this for security & configuraiton simplicity since it means that you don't have to manage exposing your rivetkit applications' networkig to rivet. instead, anything that can open a socket to rivet can accept inbound traffic to actors. + +### gateway + +- incoming traffic to actors come to the Rivet gateway and are routed to the appropriate runner +- the rivet gateway automatically handles: + - multi-region routing to route traffic to the correct reigon for an actor + - automatically waking the actor if needed + - sending traffic over the runner + +### hibernating websockets + +- hibernating web sockets are a core component of live actor migration & fault tolerance. it allows us to maintain an open websocket while the actor crashes, upgrades, or moves to another runner. +TODO: copy the rest of this from low-level webosckets document and rephrase + +### actor health endpoin + +- actors provide a simple, utility health endpoint at `/health` that lets you check if your actor is reachable (e.g. `curl https://api.rivet.dev/gateway/{actor id}/health`) + +## multi-region + +### networking + +- actors may live in different regions than inbound requests +- rive tuses the Epoxy (link again) system to handle global routing to route traffic to the correct region with high performance +- this is completely transparent to you. your app sends traffic to https://api.rivet.dev/gatewa/* and it automatically routes to the correct actor in the appropirate region + +### globally unique actor keys + +- acotr keys are globally unique to be able to benefit from multi-region capabilities without any extra work +- see more about globally uniuqe actor keys above +- see the actor keys document + +### regional endpoints + +- each reigon has a regional endpoint +- this endpoint is used specifically for connecting runners (for example https://api-us-east-1.rivet.dev), opt to use api.rivet.dev for all other traffic +- runners are required to connect to the regional endpoints + - this is because runners are sensitive to latency to the rivet regional datacenter + - we add datacenters regularly so each runner needs to be pinned to a single datacenter in order to ensure your availble datacneter list doesn't change sporadically without your consent + +### persistence + +- data is always persisted in the same region that is written +- this is important for minimal coldstarts & data locality laws + +## namespaces + +- rivet provides namespaces to run multiple actor systems in isolation +- this makes it really easy to have prod/staging environments or completely different applications running on the same rivet instance +- when you connect to rivet, you can specify which namespace you're connecting to +- self-hotsed rivet defaults to namespace "default" +- rivet cloud provdies isolated tokens for each namespace + +## manager api + +- rivet provides a standard rest api for managing actors + - useful endoints include: + - get /actors + - delete /actors/{} + - get /actors/names -> get all actor types available + +## comparison to prior art for actors + +### runtime + +- there are very few serious actor implementation targeted at the javascirpt eocsystem. rivet is arguably the most serious open-source actor implementation for typescript out there. + +### library vs orchestrator + +- some actor systems opt to be purely a library while rivet opts to have an orchestrator (i.e. the single rust binary) +- this lets us to a lot of things other actor systems can't: + - separating orchestration, persistence, and proxy lets us isoalte the core to be incredibly reliable while the fast-changing applications that ocnnect to rivet can be more error-prone safely. with a library, the blast radius of your application also affects the entire actor system. + - support for serverless platforms to benefit from cost, multi-region, blitz scaling, and relibaiblity benefits + - optimize fault tolerance since we can make more assumtions about application state when the rivet core does not crash and your app does + +### scheduling + +actors is a loose term, but there are generally 2 types of schedulign in practice: + +- ephemeral actors + - examples: erlang/otp, akka, swift + - provides no persistence or sleeping mechanism by defualt + - relies on supervisors for managing persistence +- [virtual actors](https://www.microsoft.com/en-us/research/project/orleans-virtual-actors/) + - an extension of the actor pattern that provides actors that can hibernate ("sleep") when not in use + - examples: orleans, dapr, durable objects + +rivet has similarities with both to provide more flexibility: + +- crash policies provdie for 3 types of actors: + - sleep -> most similar to virutal actors + - restart -> most similar to ephemeral actors but with a supervisor to auto-restart, however still has a durable queue ot handle backpressure + - crash -> most similar to traditional actors but with no supervisor to restart, however still has a durable queue to handle backpressure + +### communication + +- many actor frameworks use inbox patterns (think: queue-per-actor) to handle sending messages between actors +- there is no callback mechanims, instead you need to send messages back to the actual actor +- rivet opts to behave like web standards instead of using the message pattern + - actors can impelment the inbox pattern optionally + - but we provide lower-level networking to be able to be compatible with more techniologies + - rivet assumes the same serial concurerntly that other actors do (by the nature of javascript being single-threaded) but we allow you to run promises in parallel or handl eyour own concurrency control (which some other actor frameworks might require a spawning new actor to do) -1. **Standalone**: Simple, great for development -2. **Partition**: Best scaling & cost for production -3. **Coordinate**: Good for specialized deployment scenarios diff --git a/website/src/content/docs/general/images/architecture-base.png b/website/src/content/docs/general/images/architecture-base.png deleted file mode 100644 index 27a1f64972653d16a7c6fbad19635a24743bbcab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 243331 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 Ln7?e9N+(MG9F!tV|7 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%0A_@p>k# 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

PQ*)c| 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 z zD8oM{@=j*$gPEPoA}e`)a+(P9bqCp=U#%Jp(w_g1eAD)dNx{JSp!3lHX++tqK@s3Y`!< zd5|~zSJ%D-Hx&QvNWdR5QIDNrNmLSjIn^p8y5!7oD%9UgM}m`yT;~GJtR5rtw|EMo z7ak7lj1BEu)T#>#kd#w9CskOt!SV)0KheRXG_4a2+nmR+MloG7=9+zi$4L}SK{>-E zn}QlZ&V!m{{-pn&Q@y5;;KdQlzbyf-R`X z?lv~?Ncc$h(S)WSu zr1b^0qbPSO0za`^>lCpOUo`UXg-Yz-Z0ZyE1gY zR|!)*(g7DFPa#Whb2Mm;5wt|{hiFZ}m?q~0twfk!NOn-9E-PW7s(GdIMJAVx5NU4o z5t)YrVLL1NlL#P1htGAczgy-|TJ2O=+V(=^LxiV52PomluCv#`lgH@Z_X=0o)$!*3 z>#h9-d_4N5>+66sY2UD4{@5mwp&}Q}PwVV)KNDjx<6BY~fSDMhZz0PZbgcBp?}vze zmAyuGKifTOPM%&5cjrYG`d$1*yL<@HuXcx+DTBE%$A@yL?CX-yOp6K;-iN+tsubxi zeJib!YpoC1_<# zMu(Js`sEU{MCkz=V~QjKBX{6eP&_Gz+<<)i_+>n6X8V4}1NW-`ZffIhK6t3kI6&d&KS-CqAlX>sho^8AqY zrJ4=jY4 zXoZ@*N*U9iN)a}wv$h)Q>m67lk8~Pci-qFCDSEzGY2Xm_t;aw#q9Tzo<1KP|rlmxv zQ>}0PN`#QTFVs6=m>rwI!L{uP__qLUot`LSnxV)b_t*f?@Q=eKyH+MDZnK$NYSiQY zM)Gs$>bdPAictJnHCB=X?9zJBQk~r}02l{2v*%0DMLeXO!-km}IFSU#mxTbkX{wC7 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 diff --git a/website/src/content/docs/general/images/architecture-coordinate.png b/website/src/content/docs/general/images/architecture-coordinate.png deleted file mode 100644 index 008fff96c31092bfac77dfb497621bb3efa8b0d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 303798 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 z

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 - + Deploy Rivet applications with Railway's simple platform-as-a-service - + Run Rivet actors on Cloudflare's edge computing platform diff --git a/website/src/content/docs/general/system-architecture.mdx b/website/src/content/docs/general/system-architecture.mdx deleted file mode 100644 index 04a6065e32..0000000000 --- a/website/src/content/docs/general/system-architecture.mdx +++ /dev/null @@ -1,19 +0,0 @@ -import imgArchitectureBase from "./images/architecture-base.png"; -import imgArchitectureCoordinate from "./images/architecture-coordinate.png"; - -# System Architecture - - - This document is for advanced users seeking to understand the internal architecture of RivetKit. Most users do not need to read this document. - - -## Request Lifecycle - -### Base Architecture - - - -### Coordinated Architecture - - - diff --git a/website/src/content/docs/general/webhooks.mdx b/website/src/content/docs/general/webhooks.mdx deleted file mode 100644 index c9046209ee..0000000000 --- a/website/src/content/docs/general/webhooks.mdx +++ /dev/null @@ -1,3 +0,0 @@ -# Webhooks - -TODO diff --git a/website/src/content/docs/index.mdx b/website/src/content/docs/index.mdx index 6d0b538e23..895f16b686 100644 --- a/website/src/content/docs/index.mdx +++ b/website/src/content/docs/index.mdx @@ -11,23 +11,19 @@ import { # Overview -Rivet is a library for long-lived processes with durable state, realtime, and scalability. It is easily self-hostable and works with your infrastructure. - -# Quickstart - Get started with Rivet in minutes. Choose your preferred framework or runtime to begin building with actors. - + Set up actors with Node.js, Bun, and web frameworks - + Build real-time React applications with actors - + Build server-rendered Next.js experiences backed by actors - + Deploy actors on Cloudflare Workers with zero infrastructure diff --git a/website/src/content/docs/integrations/better-auth.mdx b/website/src/content/docs/integrations/better-auth.mdx deleted file mode 100644 index b6c9c99a2d..0000000000 --- a/website/src/content/docs/integrations/better-auth.mdx +++ /dev/null @@ -1,406 +0,0 @@ -# Better Auth - -Integrate Rivet with Better Auth for authentication - -Better Auth provides a comprehensive authentication solution that integrates seamlessly with Rivet Actors using the `onAuth` hook. - - - - Check out the complete example - - - -## Installation - -Install Better Auth alongside Rivet: - -```bash -npm install better-auth better-sqlite3 -npm install -D @types/better-sqlite3 - -# For React integration -npm install @rivetkit/react -``` - - - This example uses SQLite to keep the example. In production, replace this with a database like Postgres. Read more about [configuring your database in Better Auth](https://www.better-auth.com/docs/installation#configure-database). - - -## Backend Setup - - - -Create your authentication configuration: - -```typescript auth.ts -import { betterAuth } from "better-auth"; -import Database from "better-sqlite3"; - -export const auth = betterAuth({ - database: new Database("/tmp/auth.sqlite"), - trustedOrigins: ["http://localhost:5173"], - emailAndPassword: { - enabled: true, - }, -}); -``` - - - -Create and apply the database schema: - -```bash -# Generate migration files -pnpm dlx @better-auth/cli@latest generate --config auth.ts - -# Apply migrations to create the database tables -pnpm dlx @better-auth/cli@latest migrate --config auth.ts -y -``` - - - -Use the `onAuth` hook to validate sessions: - -```typescript registry.ts -import { actor, setup } from "rivetkit"; -import { Unauthorized } from "rivetkit/errors"; -import { auth } from "./auth"; - -export const chatRoom = actor({ - // Validate authentication before actor access - onAuth: async (opts) => { - const { req } = opts; - - // Use Better Auth to validate the session - const authResult = await auth.api.getSession({ - headers: req.headers, - }); - if (!authResult) throw new Unauthorized(); - - // Return user data to be available in actor - return { - user: authResult.user, - session: authResult.session, - }; - }, - - state: { - messages: [] as Array<{ - id: string; - userId: string; - username: string; - message: string; - timestamp: number; - }>, - }, - - actions: { - sendMessage: (c, message: string) => { - // Access authenticated user data - const { user } = c.conn.auth; - - const newMessage = { - id: crypto.randomUUID(), - userId: user.id, - username: user.name, - message, - timestamp: Date.now(), - }; - - c.state.messages.push(newMessage); - c.broadcast("newMessage", newMessage); - - return newMessage; - }, - - getMessages: (c) => c.state.messages, - }, -}); - -export const registry = setup({ - use: { chatRoom }, -}); -``` - - - -Configure your server to handle Better Auth routes and Rivet: - -```typescript -// server.ts -import { registry } from "./registry"; -import { auth } from "./auth"; -import { Hono } from "hono"; -import { cors } from "hono/cors"; -import { ALLOWED_PUBLIC_HEADERS } from "rivetkit"; -import { serve } from "@hono/node-server"; - -registry.start(); -const app = new Hono(); - -// Configure CORS for Better Auth + Rivet -app.use("*", cors({ - // Where your frontend is running - origin: ["http://localhost:5173"], - // ALLOWED_PUBLIC_HEADERS are headers required for Rivet to operate - allowHeaders: ["Authorization", ...ALLOWED_PUBLIC_HEADERS], - allowMethods: ["POST", "GET", "OPTIONS"], - exposeHeaders: ["Content-Length"], - maxAge: 600, - credentials: true, -})); - -// Mount Better Auth routes -app.on(["GET", "POST"], "/api/auth/**", (c) => - auth.handler(c.req.raw) -); - -// Start Rivet server -serve(app); -``` - - - -## Frontend Integration - - - -Create a Better Auth client for your frontend: - -```typescript -// auth-client.ts -import { createAuthClient } from "better-auth/react"; - -export const authClient = createAuthClient({ - baseURL: "http://localhost:8080", -}); -``` - - - -Create login/signup forms: - -```tsx -// AuthForm.tsx -import React, { useState } from "react"; -import { authClient } from "./auth-client"; - -export function AuthForm() { - const [isLogin, setIsLogin] = useState(true); - const [email, setEmail] = useState(""); - const [password, setPassword] = useState(""); - const [name, setName] = useState(""); - - const handleSubmit = async (e: React.FormEvent) => { - e.preventDefault(); - - try { - if (isLogin) { - await authClient.signIn.email({ email, password }); - } else { - await authClient.signUp.email({ email, password, name }); - } - } catch (error) { - console.error("Auth error:", error); - } - }; - - return ( -
-

{isLogin ? "Sign In" : "Sign Up"}

- - {!isLogin && ( - setName(e.target.value)} - required - /> - )} - - setEmail(e.target.value)} - required - /> - - setPassword(e.target.value)} - required - /> - - - - -
- ); -} -``` -
- - -Use authenticated sessions with Rivet: - -```tsx -// ChatRoom.tsx -import React, { useState } from "react"; -import { createRivetKit } from "@rivetkit/react"; -import { authClient } from "./auth-client"; -import type { registry } from "../backend/registry"; - -const { useActor } = createRivetKit("http://localhost:8080"); - -interface ChatRoomProps { - session: { user: { id: string; name: string } }; - roomId: string; -} - -export function ChatRoom({ session, roomId }: ChatRoomProps) { - const [newMessage, setNewMessage] = useState(""); - - const chatRoom = useActor({ - name: "chatRoom", - key: [roomId], - }); - - const sendMessage = async () => { - if (!newMessage.trim()) return; - - await chatRoom.sendMessage(newMessage); - setNewMessage(""); - }; - - return ( -
-
- Welcome, {session.user.name}! - -
- -
- {chatRoom.state.messages.map(msg => ( -
- {msg.username}: {msg.message} -
- ))} -
- -
- setNewMessage(e.target.value)} - onKeyPress={(e) => e.key === "Enter" && sendMessage()} - placeholder="Type a message..." - /> - -
-
- ); -} -``` -
-
- -## Advanced Features - -### Role-Based Access - -Add role checking to your actors: - -```typescript -export const adminActor = actor({ - onAuth: async (opts) => { - const authResult = await auth.api.getSession({ - headers: opts.req.headers, - }); - if (!authResult) throw new Unauthorized(); - - return { user: authResult.user }; - }, - - actions: { - deleteUser: (c, userId: string) => { - // Check user role (assuming you store roles in user data) - const { user } = c.conn.auth; - if (user.role !== "admin") { - throw new Unauthorized("Admin access required"); - } - - // Admin-only action - // ... implementation - }, - }, -}); -``` - -### Session Management - -Handle session expiration gracefully: - -```tsx -// hooks/useAuth.ts -import { authClient } from "./auth-client"; -import { useEffect } from "react"; - -export function useAuthWithRefresh() { - const { data: session, error } = authClient.useSession(); - - useEffect(() => { - if (error?.message?.includes("session")) { - // Redirect to login on session expiration - window.location.href = "/login"; - } - }, [error]); - - return session; -} -``` - -## Production Deployment - -For production, you'll need a database from a provider like [Neon](https://neon.tech/), [PlanetScale](https://planetscale.com/), [AWS RDS](https://aws.amazon.com/rds/), or [Google Cloud SQL](https://cloud.google.com/sql). - -Configure your production database connection: - -```typescript -// auth.ts -import { betterAuth } from "better-auth"; -import { Pool } from "pg"; - -export const auth = betterAuth({ - database: new Pool({ - connectionString: process.env.DATABASE_URL, - }), - trustedOrigins: [process.env.FRONTEND_URL], - emailAndPassword: { enabled: true }, -}); -``` - -Set the following environment variables for production: - -```bash -DATABASE_URL=postgresql://username:password@localhost:5432/myapp -FRONTEND_URL=https://myapp.com -BETTER_AUTH_SECRET=your-secure-secret-key -BETTER_AUTH_URL=https://api.myapp.com -``` - -Read more about [configuring Postgres with Better Auth](https://www.better-auth.com/docs/adapters/postgresql). - - - Don't forget to re-generate & re-apply your database migrations if you change the database in your Better Auth config. - - diff --git a/website/src/content/docs/integrations/cloudflare-workers.mdx b/website/src/content/docs/integrations/cloudflare-workers.mdx index b5a8a71cea..c2b68bb373 100644 --- a/website/src/content/docs/integrations/cloudflare-workers.mdx +++ b/website/src/content/docs/integrations/cloudflare-workers.mdx @@ -8,7 +8,6 @@ Deploy Rivet Actors to Cloudflare Workers with Durable Objects for global edge c | --- | --- | | Horizontal scaling | Yes | | WebSockets | Yes | -| SSE | Yes | | Edge | Yes | | Scheduling | Yes | diff --git a/website/src/content/docs/openapi.json b/website/src/content/docs/openapi.json deleted file mode 100644 index 0d0de4ee85..0000000000 --- a/website/src/content/docs/openapi.json +++ /dev/null @@ -1,305 +0,0 @@ -{ - "openapi": "3.0.0", - "info": { - "version": "0.9.0", - "title": "RivetKit API" - }, - "components": { - "schemas": { - "ResolveResponse": { - "type": "object", - "properties": { - "i": { - "type": "string", - "example": "actor-123" - } - }, - "required": ["i"] - }, - "ResolveQuery": { - "type": "object", - "properties": { - "query": { - "nullable": true, - "example": { - "getForId": { - "actorId": "actor-123" - } - } - } - } - }, - "ActionResponse": { - "nullable": true - }, - "ActionRequest": { - "type": "object", - "properties": { - "query": { - "nullable": true, - "example": { - "getForId": { - "actorId": "actor-123" - } - } - }, - "body": { - "nullable": true, - "example": { - "param1": "value1", - "param2": 123 - } - } - } - }, - "ConnectionMessageResponse": { - "nullable": true - }, - "ConnectionMessageRequest": { - "type": "object", - "properties": { - "message": { - "nullable": true, - "example": { - "type": "message", - "content": "Hello, actor!" - } - } - } - } - }, - "parameters": {} - }, - "paths": { - "/actors/resolve": { - "post": { - "parameters": [ - { - "schema": { - "type": "string", - "description": "Actor query information" - }, - "required": true, - "name": "X-RivetKit-Query", - "in": "header" - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResolveQuery" - } - } - } - }, - "responses": { - "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResolveResponse" - } - } - } - }, - "400": { - "description": "User error" - }, - "500": { - "description": "Internal error" - } - } - } - }, - "/actors/connect/websocket": { - "get": { - "responses": { - "101": { - "description": "WebSocket upgrade" - } - } - } - }, - "/actors/connect/sse": { - "get": { - "parameters": [ - { - "schema": { - "type": "string", - "description": "The encoding format to use for the response (json, cbor)", - "example": "json" - }, - "required": true, - "name": "X-RivetKit-Encoding", - "in": "header" - }, - { - "schema": { - "type": "string", - "description": "Actor query information" - }, - "required": true, - "name": "X-RivetKit-Query", - "in": "header" - }, - { - "schema": { - "type": "string", - "description": "Connection parameters" - }, - "required": false, - "name": "X-RivetKit-Conn-Params", - "in": "header" - } - ], - "responses": { - "200": { - "description": "SSE stream", - "content": { - "text/event-stream": { - "schema": { - "nullable": true - } - } - } - } - } - } - }, - "/actors/actions/{action}": { - "post": { - "parameters": [ - { - "schema": { - "type": "string", - "example": "myAction" - }, - "required": true, - "name": "action", - "in": "path" - }, - { - "schema": { - "type": "string", - "description": "The encoding format to use for the response (json, cbor)", - "example": "json" - }, - "required": true, - "name": "X-RivetKit-Encoding", - "in": "header" - }, - { - "schema": { - "type": "string", - "description": "Connection parameters" - }, - "required": false, - "name": "X-RivetKit-Conn-Params", - "in": "header" - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ActionRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ActionResponse" - } - } - } - }, - "400": { - "description": "User error" - }, - "500": { - "description": "Internal error" - } - } - } - }, - "/actors/message": { - "post": { - "parameters": [ - { - "schema": { - "type": "string", - "description": "Actor ID (used in some endpoints)", - "example": "actor-123456" - }, - "required": true, - "name": "X-RivetKit-Actor", - "in": "header" - }, - { - "schema": { - "type": "string", - "description": "Connection ID", - "example": "conn-123456" - }, - "required": true, - "name": "X-RivetKit-Conn", - "in": "header" - }, - { - "schema": { - "type": "string", - "description": "The encoding format to use for the response (json, cbor)", - "example": "json" - }, - "required": true, - "name": "X-RivetKit-Encoding", - "in": "header" - }, - { - "schema": { - "type": "string", - "description": "Connection token" - }, - "required": true, - "name": "X-RivetKit-Conn-Token", - "in": "header" - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConnectionMessageRequest" - } - } - } - }, - "responses": { - "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConnectionMessageResponse" - } - } - } - }, - "400": { - "description": "User error" - }, - "500": { - "description": "Internal error" - } - } - } - } - } -} diff --git a/website/src/data/deploy/shared.ts b/website/src/data/deploy/shared.ts index 1e02b2739e..1b05fcf232 100644 --- a/website/src/data/deploy/shared.ts +++ b/website/src/data/deploy/shared.ts @@ -30,7 +30,7 @@ export const deployGroups: DeployGroup[] = [ items: [ { title: "Vercel", - href: "/docs/deploy/vercel", + href: "/docs/connect/vercel", description: "Deploy Next.js + RivetKit apps to Vercel's edge network", icon: faVercel, @@ -39,7 +39,7 @@ export const deployGroups: DeployGroup[] = [ }, { title: "Cloudflare Workers", - href: "/docs/deploy/cloudflare-workers", + href: "/docs/connect/cloudflare-workers", description: "Run your app on Cloudflare's global edge network with Durable Objects", icon: faCloudflare, @@ -52,7 +52,7 @@ export const deployGroups: DeployGroup[] = [ items: [ { title: "Railway", - href: "/docs/deploy/railway", + href: "/docs/connect/railway", description: "Deploy containers to Railway's managed infrastructure", icon: faRailway, @@ -60,21 +60,21 @@ export const deployGroups: DeployGroup[] = [ }, { title: "Kubernetes", - href: "/docs/deploy/kubernetes", + href: "/docs/connect/kubernetes", description: "Deploy to any Kubernetes cluster with container images", icon: faKubernetes, }, { title: "AWS ECS", - href: "/docs/deploy/aws-ecs", + href: "/docs/connect/aws-ecs", description: "Run containerized workloads on Amazon Elastic Container Service", icon: faAws, }, { title: "Google Cloud Run", - href: "/docs/deploy/gcp-cloud-run", + href: "/docs/connect/gcp-cloud-run", description: "Deploy containers to Google Cloud Run for auto-scaling", icon: faGoogleCloud, @@ -82,18 +82,18 @@ export const deployGroups: DeployGroup[] = [ ], }, { - title: "Self-Hosted", + title: "Virtual Machines", items: [ { title: "Hetzner", - href: "/docs/deploy/hetzner", + href: "/docs/connect/hetzner", description: "Deploy to Hetzner's cost-effective cloud infrastructure", icon: faHetzner, }, { title: "VM & Bare Metal", - href: "/docs/deploy/vm-and-bare-metal", + href: "/docs/connect/vm-and-bare-metal", description: "Run on virtual machines or bare metal servers with full control", icon: faServer, diff --git a/website/src/data/integrations/shared.ts b/website/src/data/integrations/shared.ts index 6aeedf42c8..09d85bd6dd 100644 --- a/website/src/data/integrations/shared.ts +++ b/website/src/data/integrations/shared.ts @@ -43,17 +43,17 @@ export const integrationGroups: IntegrationGroup[] = [ }, ], }, - { - title: "Auth", - items: [ - { - title: "Better Auth", - href: "/docs/integrations/better-auth", - description: - "Modern authentication library with TypeScript support", - }, - ], - }, + // { + // title: "Auth", + // items: [ + // { + // title: "Better Auth", + // href: "/docs/integrations/better-auth", + // description: + // "Modern authentication library with TypeScript support", + // }, + // ], + // }, { title: "Misc", items: [ diff --git a/website/src/sitemap/mod.ts b/website/src/sitemap/mod.ts index 62186d3742..00a96bc9b7 100644 --- a/website/src/sitemap/mod.ts +++ b/website/src/sitemap/mod.ts @@ -41,6 +41,7 @@ import { faNodeJs, faPaintbrush, faPalette, + faPuzzlePiece, faRailway, faReact, faRecycle, @@ -71,17 +72,6 @@ import { useCases } from "@/data/use-cases"; import nextjs from "@/images/vendors/next-js.svg"; import type { SidebarItem, Sitemap } from "@/lib/sitemap"; -// Goals: -// - Siebar links should advertise the product, collapse any advanced pages away -// - The sidebar should be 1 screen height when collapsed - -// Profiles: -// - What does Rivet do? -// - Does it work for my use cases -> Use Cases -// - Curious about the technology -> Build with Rivet -// - Just want to jump in -// - People who want to run Open Source - const deploySidebarSections: SidebarItem[] = deployGroups.map( ({ title: groupTitle, items }) => ({ title: groupTitle, @@ -218,9 +208,9 @@ export const sitemap = [ //icon: faTag, }, { - title: "Helper Types", - href: "/docs/actors/helper-types", - //icon: faCode, + title: "Destroying", + href: "/docs/actors/destroy", + //icon: faTag, }, ], }, @@ -245,15 +235,27 @@ export const sitemap = [ //icon: faArrowsTurnToDots, }, { - title: "Fetch & WebSocket Handler", - href: "/docs/actors/fetch-and-websocket-handler", - //icon: faLink, + title: "Low-Level WebSocket Handler", + href: "/docs/actors/websocket-handler" + }, + { + title: "Low-Level HTTP Handler", + href: "/docs/actors/request-handler" + }, + { + title: "Vanilla HTTP API", + href: "/docs/actors/http-api" }, ], }, { - title: "Data Management", - icon: faDatabase, + title: "Design Patterns", + icon: faLayerGroup, + href: "/docs/actors/design-patterns", + }, + { + title: "More", + icon: faSitemap, collapsible: true, pages: [ { @@ -261,42 +263,34 @@ export const sitemap = [ href: "/docs/actors/ephemeral-variables", //icon: faMemory, }, - { - title: "Sharing & Joining State", - href: "/docs/actors/sharing-and-joining-state", - //icon: faMerge, - }, { title: "External SQL", href: "/docs/actors/external-sql", //icon: faDatabase, }, - ], - }, - { - title: "More", - icon: faSitemap, - collapsible: true, - pages: [ + { + title: "Errors", + href: "/docs/actors/errors" + }, { title: "Testing", href: "/docs/actors/testing", - icon: faVialCircleCheck, + // icon: faVialCircleCheck, + }, + { + title: "Helper Types", + href: "/docs/actors/helper-types", + //icon: faCode, }, { title: "CORS", href: "/docs/general/cors", - icon: faShareNodes, + // icon: faShareNodes, }, { title: "Logging", href: "/docs/general/logging", - icon: faListUl, - }, - { - title: "Scaling & Concurrency", - href: "/docs/actors/scaling", - //icon: faMaximize, + // icon: faListUl, }, ], }, @@ -329,16 +323,11 @@ export const sitemap = [ href: "/docs/clients/next-js", icon: faNextjs, }, - { - title: "Rust", - href: "/docs/clients/rust", - icon: faRust, - }, - { - title: "OpenAPI", - href: "/docs/clients/openapi", - icon: faFileImport, - }, + // { + // title: "Rust", + // href: "/docs/clients/rust", + // icon: faRust, + // }, ] } ], @@ -351,6 +340,35 @@ export const sitemap = [ // href: "/docs/general/studio", // icon: faPalette, // }, + { + title: "API Reference", + collapsible: true, + pages: [ + { + title: "TypeScript API", + href: "/typedoc", + external: true + // icon: faSquareBinary, + }, + { + title: "OpenAPI", + href: "https://github.com/rivet-dev/rivet/tree/main/rivetkit-openapi", + external: true + // icon: faSquareBinary, + }, + { + title: "AsyncAPI", + href: "https://github.com/rivet-dev/rivet/tree/main/rivetkit-asyncapi", + external: true + // icon: faSquareBinary, + }, + ] + }, + { + title: "Architecture", + href: "/docs/general/architecture", + // icon: faSquareBinary, + }, { title: "Docs for LLMs", href: "/docs/general/docs-for-llms",