From 8df011840b9b6e2fa9d327dcfecee50dfdf561a9 Mon Sep 17 00:00:00 2001 From: "rivet-docs-sync[bot]" Date: Tue, 3 Nov 2026 22:23:40 +0000 Subject: [PATCH 1/5] docs(api): sync from rivet-dev/rivet@bd7d642 --- vendor/api/docs/content/actors/create.mdx | 31 +- vendor/api/docs/content/actors/destroy.mdx | 8 +- .../api/docs/content/actors/get-or-create.mdx | 23 +- vendor/api/docs/content/actors/get.mdx | 194 -- vendor/api/docs/content/actors/list-names.mdx | 10 +- vendor/api/docs/content/actors/list.mdx | 24 +- vendor/api/docs/content/actors/reschedule.mdx | 10 +- vendor/api/docs/content/actors/sleep.mdx | 8 +- vendor/api/docs/content/authentication.mdx | 2 +- .../content/control-plane/datacenters.mdx | 6 +- .../docs/content/control-plane/metadata.mdx | 6 +- vendor/api/docs/content/gateway/request.mdx | 70 - vendor/api/docs/content/index.mdx | 3 +- vendor/api/docs/content/inspector-connect.mdx | 525 ---- vendor/api/docs/content/inspector/action.mdx | 99 - .../docs/content/inspector/connections.mdx | 86 - .../content/inspector/database-execute.mdx | 84 - .../docs/content/inspector/database-rows.mdx | 73 - .../content/inspector/database-schema.mdx | 86 - .../docs/content/inspector/queue-delete.mdx | 57 - .../api/docs/content/inspector/queue-get.mdx | 105 - .../api/docs/content/inspector/queue-post.mdx | 83 - vendor/api/docs/content/inspector/rpcs.mdx | 84 - .../api/docs/content/inspector/state-get.mdx | 86 - .../docs/content/inspector/state-patch.mdx | 100 - vendor/api/docs/content/inspector/summary.mdx | 100 - vendor/api/docs/content/inspector/traces.mdx | 96 - .../content/inspector/workflow-history.mdx | 86 - .../content/inspector/workflow-replay.mdx | 98 - vendor/api/docs/content/namespaces/create.mdx | 11 +- vendor/api/docs/content/namespaces/list.mdx | 10 +- vendor/api/docs/content/pools/delete.mdx | 16 +- vendor/api/docs/content/pools/get.mdx | 12 +- vendor/api/docs/content/pools/list-nodes.mdx | 18 +- vendor/api/docs/content/pools/list.mdx | 14 +- vendor/api/docs/content/pools/upsert.mdx | 17 +- vendor/api/docs/content/tokens/create.mdx | 14 +- vendor/api/docs/content/tokens/inspect.mdx | 6 +- vendor/api/docs/content/worker-connect.mdx | 4 +- vendor/api/docs/endpoints.json | 2222 +++++++---------- vendor/api/docs/error-registry.json | 100 +- vendor/api/docs/sidebar.json | 117 +- vendor/api/engine/artifacts/openapi.json | 27 +- .../actors-quickstart-next-js/registry.ts | 16 - .../{ => backend}/index.ts | 0 .../{ => frontend}/Counter.tsx | 6 +- .../actors-quickstart-react/frontend/main.tsx | 9 + .../actors-versions/programmatic-version.ts | 10 - .../api/examples/docs/api/actors-destroy.ts | 2 +- .../examples/docs/api/actors-list-names.ts | 2 +- vendor/api/examples/docs/api/actors-list.ts | 2 +- .../examples/docs/api/actors-reschedule.ts | 2 +- vendor/api/examples/docs/api/actors-sleep.ts | 2 +- .../examples/docs/api/connection-actions.ts | 2 +- .../examples/docs/api/connection-connect.ts | 2 +- .../examples/docs/api/connection-errors.ts | 2 +- .../examples/docs/api/connection-events.ts | 2 +- .../docs/api/control-plane-datacenters.ts | 2 +- .../docs/api/control-plane-metadata.ts | 2 +- .../api/examples/docs/api/gateway-metadata.ts | 2 +- vendor/api/examples/docs/api/gateway-queue.ts | 2 +- .../api/examples/docs/api/inspector-action.ts | 14 - .../docs/api/inspector-connections.ts | 7 - .../docs/api/inspector-database-execute.ts | 17 - .../docs/api/inspector-database-rows.ts | 12 - .../docs/api/inspector-database-schema.ts | 7 - .../docs/api/inspector-queue-delete.ts | 10 - .../examples/docs/api/inspector-queue-get.ts | 7 - .../examples/docs/api/inspector-queue-post.ts | 14 - .../api/examples/docs/api/inspector-rpcs.ts | 7 - .../examples/docs/api/inspector-state-get.ts | 7 - .../docs/api/inspector-state-patch.ts | 14 - .../examples/docs/api/inspector-summary.ts | 7 - .../api/examples/docs/api/inspector-traces.ts | 7 - .../docs/api/inspector-workflow-history.ts | 7 - .../docs/api/inspector-workflow-replay.ts | 14 - .../examples/docs/api/namespaces-create.ts | 2 +- .../api/examples/docs/api/namespaces-list.ts | 2 +- vendor/api/examples/docs/api/pools-delete.ts | 16 + vendor/api/examples/docs/api/pools-get.ts | 13 + .../api/examples/docs/api/pools-list-nodes.ts | 14 + ...{workers-configs-list.ts => pools-list.ts} | 8 +- ...kers-configs-upsert.ts => pools-upsert.ts} | 8 +- .../api/examples/docs/api/tokens-inspect.ts | 2 +- .../docs/api/workers-configs-delete.ts | 13 - .../api/workers-configs-refresh-metadata.ts | 2 +- vendor/api/examples/docs/api/workers-list.ts | 12 - .../api/workers-serverless-health-check.ts | 2 +- .../docs/cookbook-cron-jobs/daily-report.ts | 18 - .../examples/docs/durable-streams/client.ts | 14 + .../examples/docs/durable-streams/create.ts | 11 + .../examples/docs/durable-streams/producer.ts | 21 + .../docs/durable-streams/read-history.ts | 10 + .../docs/durable-streams/read-live.ts | 14 + .../examples/docs/durable-streams/write.ts | 13 + .../api/examples/docs/general-edge/client.ts | 12 + .../docs/general-jwt/quickstart/client.ts | 2 +- .../examples/docs/onboarding-actors/client.ts | 20 + .../examples/docs/onboarding-actors/index.ts | 43 + vendor/api/examples/docs/package.json | 4 +- vendor/api/examples/docs/tsconfig.json | 9 +- vendor/api/rivetkit-asyncapi/asyncapi.json | 2 +- 102 files changed, 1333 insertions(+), 4003 deletions(-) delete mode 100644 vendor/api/docs/content/actors/get.mdx delete mode 100644 vendor/api/docs/content/gateway/request.mdx delete mode 100644 vendor/api/docs/content/inspector-connect.mdx delete mode 100644 vendor/api/docs/content/inspector/action.mdx delete mode 100644 vendor/api/docs/content/inspector/connections.mdx delete mode 100644 vendor/api/docs/content/inspector/database-execute.mdx delete mode 100644 vendor/api/docs/content/inspector/database-rows.mdx delete mode 100644 vendor/api/docs/content/inspector/database-schema.mdx delete mode 100644 vendor/api/docs/content/inspector/queue-delete.mdx delete mode 100644 vendor/api/docs/content/inspector/queue-get.mdx delete mode 100644 vendor/api/docs/content/inspector/queue-post.mdx delete mode 100644 vendor/api/docs/content/inspector/rpcs.mdx delete mode 100644 vendor/api/docs/content/inspector/state-get.mdx delete mode 100644 vendor/api/docs/content/inspector/state-patch.mdx delete mode 100644 vendor/api/docs/content/inspector/summary.mdx delete mode 100644 vendor/api/docs/content/inspector/traces.mdx delete mode 100644 vendor/api/docs/content/inspector/workflow-history.mdx delete mode 100644 vendor/api/docs/content/inspector/workflow-replay.mdx delete mode 100644 vendor/api/examples/docs/actors-quickstart-next-js/registry.ts rename vendor/api/examples/docs/actors-quickstart-react/{ => backend}/index.ts (100%) rename vendor/api/examples/docs/actors-quickstart-react/{ => frontend}/Counter.tsx (85%) create mode 100644 vendor/api/examples/docs/actors-quickstart-react/frontend/main.tsx delete mode 100644 vendor/api/examples/docs/actors-versions/programmatic-version.ts delete mode 100644 vendor/api/examples/docs/api/inspector-action.ts delete mode 100644 vendor/api/examples/docs/api/inspector-connections.ts delete mode 100644 vendor/api/examples/docs/api/inspector-database-execute.ts delete mode 100644 vendor/api/examples/docs/api/inspector-database-rows.ts delete mode 100644 vendor/api/examples/docs/api/inspector-database-schema.ts delete mode 100644 vendor/api/examples/docs/api/inspector-queue-delete.ts delete mode 100644 vendor/api/examples/docs/api/inspector-queue-get.ts delete mode 100644 vendor/api/examples/docs/api/inspector-queue-post.ts delete mode 100644 vendor/api/examples/docs/api/inspector-rpcs.ts delete mode 100644 vendor/api/examples/docs/api/inspector-state-get.ts delete mode 100644 vendor/api/examples/docs/api/inspector-state-patch.ts delete mode 100644 vendor/api/examples/docs/api/inspector-summary.ts delete mode 100644 vendor/api/examples/docs/api/inspector-traces.ts delete mode 100644 vendor/api/examples/docs/api/inspector-workflow-history.ts delete mode 100644 vendor/api/examples/docs/api/inspector-workflow-replay.ts create mode 100644 vendor/api/examples/docs/api/pools-delete.ts create mode 100644 vendor/api/examples/docs/api/pools-get.ts create mode 100644 vendor/api/examples/docs/api/pools-list-nodes.ts rename vendor/api/examples/docs/api/{workers-configs-list.ts => pools-list.ts} (52%) rename vendor/api/examples/docs/api/{workers-configs-upsert.ts => pools-upsert.ts} (59%) delete mode 100644 vendor/api/examples/docs/api/workers-configs-delete.ts delete mode 100644 vendor/api/examples/docs/api/workers-list.ts delete mode 100644 vendor/api/examples/docs/cookbook-cron-jobs/daily-report.ts create mode 100644 vendor/api/examples/docs/durable-streams/client.ts create mode 100644 vendor/api/examples/docs/durable-streams/create.ts create mode 100644 vendor/api/examples/docs/durable-streams/producer.ts create mode 100644 vendor/api/examples/docs/durable-streams/read-history.ts create mode 100644 vendor/api/examples/docs/durable-streams/read-live.ts create mode 100644 vendor/api/examples/docs/durable-streams/write.ts create mode 100644 vendor/api/examples/docs/general-edge/client.ts create mode 100644 vendor/api/examples/docs/onboarding-actors/client.ts create mode 100644 vendor/api/examples/docs/onboarding-actors/index.ts diff --git a/vendor/api/docs/content/actors/create.mdx b/vendor/api/docs/content/actors/create.mdx index e510dc90..e3bc2be7 100644 --- a/vendor/api/docs/content/actors/create.mdx +++ b/vendor/api/docs/content/actors/create.mdx @@ -1,11 +1,11 @@ --- title: "Create Actor" -description: "Create a new actor. Fails if a live actor with the same name and key already exists." +description: "Create a new actor. Fails if an actor with the same name and key already exists." --- {/* Generated by scripts/docs/gen-api-reference.mjs from engine/artifacts/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} -Prefer [Get or Create Actor](/docs/api/actors/get-or-create) for idempotent access by key. Use this endpoint when you need a fresh actor every time, for example with a random key. The request returns once the actor's record exists, and fails after 30 seconds. A namespace token needs a grant on `actor` with `create`. +Prefer [Get or Create Actor](/docs/api/actors/get-or-create) for idempotent access by key. Use this endpoint when you need a fresh actor every time, for example with a random key. ```http POST https://rivet.example.com/actors @@ -22,7 +22,8 @@ curl -X POST "https://rivet.example.com/actors?namespace=$RIVET_NAMESPACE" \ -d '{ "name": "counter", "key": "my-counter", - "runner_name_selector": "default" + "runner_name_selector": "default", + "crash_policy": "sleep" }' ``` @@ -32,13 +33,13 @@ curl -X POST "https://rivet.example.com/actors?namespace=$RIVET_NAMESPACE" \ ## Authentication -Send the admin token, or a namespace token from [Create Token](/docs/api/tokens/create) whose grants cover the request, as a bearer token in the `Authorization` header. The `x-rivet-token` header is also accepted. Routes with a `namespace` query parameter use the `default` namespace when it is omitted. See [Authentication](/docs/api/authentication). +Send your namespace token as a bearer token in the `Authorization` header. Every control plane request also requires the `namespace` query parameter. See [Authentication](/docs/api/authentication). ## Query Parameters | Name | Type | Required | Description | | --- | --- | --- | --- | -| `namespace` | `string` | No | Name of the namespace to operate in. Defaults to `default`. | +| `namespace` | `string` | No | Name of the namespace to operate in. | ## Request Body @@ -46,25 +47,25 @@ Content type: `application/json`. | Field | Type | Required | Description | | --- | --- | --- | --- | -| `name` | `string` | Yes | Name of the actor as registered in your RivetKit registry. 1 to 64 bytes. | -| `key` | `string \| null` | No | Key identifying this actor within its name. Multi-part keys are joined with `/`, see [Actor Keys](/docs/api/actor-keys). Omit for an actor without a key. | -| `input` | `string \| null` | No | Input passed to the actor, encoded as standard base64 (not base64url). | -| `runner_name_selector` | `string \| null` | No | Node pool that runs the actor. Defaults to `default`. | +| `name` | `string` | Yes | Name of the actor as registered in your RivetKit registry. | +| `key` | `string \| null` | No | Key identifying this actor within its name. Multi-part keys are joined with `/`, see [Actor Keys](/docs/api/actor-keys). Omit for a keyless actor. | +| `input` | `string \| null` | No | Base64url-encoded CBOR input passed to the actor's `createState` and `onCreate` hooks. | +| `pool` | `string \| null` | No | Name of the node pool to run the actor in. Defaults to `default`. | ## Responses ### 200 -The created actor. `created` is always `true`. +The created actor. | Field | Type | Description | | --- | --- | --- | | `actor` | `object` | | | `actor.actor_id` | `string` | Unique ID of the actor. | | `actor.name` | `string` | Actor name as registered in your RivetKit registry. | -| `actor.key` | `string` | Actor key. Multi-part keys are joined with `/`, see [Actor Keys](/docs/api/actor-keys). An empty string for an actor without a key. | +| `actor.key` | `string` | Actor key. Multi-part keys are joined with `/`, see [Actor Keys](/docs/api/actor-keys). | | `actor.namespace` | `string` | Name of the namespace the actor belongs to. | -| `actor.runner_name_selector` | `string` | Node pool the actor runs in. | +| `actor.pool` | `string` | Name of the node pool the actor runs in. | | `actor.create_ts` | `integer` | When the actor was created, in Unix milliseconds. | | `actor.start_ts` | `integer \| null` | When the actor first started. Not recorded by this version, so always `null`. | | `actor.pending_allocation_ts` | `integer \| null` | When the actor started waiting for a node. Not recorded by this version, so always `null`. | @@ -72,7 +73,7 @@ The created actor. `created` is always `true`. | `actor.sleep_ts` | `integer \| null` | When the actor went to sleep. Not recorded by this version, so always `null`. | | `actor.reschedule_ts` | `integer \| null` | When the actor will next try to allocate. Not recorded by this version, so always `null`. | | `actor.destroy_ts` | `integer \| null` | When the actor was destroyed, in Unix milliseconds. Only set in listings that include destroyed actors; otherwise `null`. | -| `created` | `boolean` | Always `true`. | +| `created` | `boolean` | `true` if this request created the actor, `false` if it already existed. | ```json { @@ -81,7 +82,7 @@ The created actor. `created` is always `true`. "name": "my-actor", "key": "my-key", "namespace": "my-namespace", - "runner_name_selector": "default", + "pool": "default", "create_ts": 1700000000000, "start_ts": null, "pending_allocation_ts": null, @@ -96,7 +97,7 @@ The created actor. `created` is always `true`. ### 400 -`actor.invalid_name`: `name` is empty or longer than 64 bytes. `actor.invalid_key`: `key` is longer than 1024 bytes. `actor.invalid_key_encoding`: `key` is not in canonical slash-separated form. `actor.key_owned_elsewhere`: another datacenter owns the key. `envoy.invalid_pool_name`: `runner_name_selector` is not a valid pool name. `envoy.invalid_namespace_name`: the `namespace` value is not a DNS label of 1 to 63 lowercase letters, digits and hyphens. +`actor.invalid_name`: `name` is empty or longer than 64 bytes. `actor.invalid_key`: `key` is longer than 1024 bytes. `actor.invalid_key_encoding`: `key` is not in canonical slash-separated form. `actor.key_owned_elsewhere`: another datacenter owns the key. `envoy.invalid_pool_name`: `pool` is not a valid pool name. `envoy.invalid_namespace_name`: the `namespace` value is not a DNS label of 1 to 63 lowercase letters, digits and hyphens. | Field | Type | Description | | --- | --- | --- | diff --git a/vendor/api/docs/content/actors/destroy.mdx b/vendor/api/docs/content/actors/destroy.mdx index c70aa07a..17ebc703 100644 --- a/vendor/api/docs/content/actors/destroy.mdx +++ b/vendor/api/docs/content/actors/destroy.mdx @@ -5,8 +5,6 @@ description: "Destroy an actor. The actor's onDestroy hook runs, then its state {/* Generated by scripts/docs/gen-api-reference.mjs from engine/artifacts/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} -A namespace token needs a grant on `actor` with `delete`. - ```http DELETE https://rivet.example.com/actors/{actor_id} ``` @@ -26,7 +24,7 @@ curl -X DELETE "https://rivet.example.com/actors/$ACTOR_ID?namespace=$RIVET_NAME ## Authentication -Send the admin token, or a namespace token from [Create Token](/docs/api/tokens/create) whose grants cover the request, as a bearer token in the `Authorization` header. The `x-rivet-token` header is also accepted. Routes with a `namespace` query parameter use the `default` namespace when it is omitted. See [Authentication](/docs/api/authentication). +Send your namespace token as a bearer token in the `Authorization` header. Every control plane request also requires the `namespace` query parameter. See [Authentication](/docs/api/authentication). ## Path Parameters @@ -38,13 +36,13 @@ Send the admin token, or a namespace token from [Create Token](/docs/api/tokens/ | Name | Type | Required | Description | | --- | --- | --- | --- | -| `namespace` | `string` | No | Name of the namespace to operate in. Defaults to `default`. | +| `namespace` | `string` | No | Name of the namespace to operate in. | ## Responses ### 200 -The destroy was accepted. The response body is an empty object. +The destroy was accepted. ```json {} diff --git a/vendor/api/docs/content/actors/get-or-create.mdx b/vendor/api/docs/content/actors/get-or-create.mdx index 34fe6b77..1e2f3140 100644 --- a/vendor/api/docs/content/actors/get-or-create.mdx +++ b/vendor/api/docs/content/actors/get-or-create.mdx @@ -5,7 +5,7 @@ description: "Return the actor with the given name and key, creating it if it do {/* Generated by scripts/docs/gen-api-reference.mjs from engine/artifacts/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} -The response includes `created`, which is `true` when this call created the actor. A sleeping actor is woken. Without `key`, a new actor is created every time. Gateway endpoints can perform the same lookup inline with the `rvt-*` selector parameters, so you only need this endpoint when you want the `actor_id` up front. A namespace token needs a grant on `actor` with `create`. +The response includes `created`, which is `true` when this call created the actor. Gateway endpoints can perform the same lookup inline with the `rvt-*` selector parameters, so you only need this endpoint when you want the `actor_id` up front. ```http PUT https://rivet.example.com/actors @@ -22,7 +22,8 @@ curl -X PUT "https://rivet.example.com/actors?namespace=$RIVET_NAMESPACE" \ -d '{ "name": "counter", "key": "my-counter", - "runner_name_selector": "default" + "runner_name_selector": "default", + "crash_policy": "sleep" }' ``` @@ -32,13 +33,13 @@ curl -X PUT "https://rivet.example.com/actors?namespace=$RIVET_NAMESPACE" \ ## Authentication -Send the admin token, or a namespace token from [Create Token](/docs/api/tokens/create) whose grants cover the request, as a bearer token in the `Authorization` header. The `x-rivet-token` header is also accepted. Routes with a `namespace` query parameter use the `default` namespace when it is omitted. See [Authentication](/docs/api/authentication). +Send your namespace token as a bearer token in the `Authorization` header. Every control plane request also requires the `namespace` query parameter. See [Authentication](/docs/api/authentication). ## Query Parameters | Name | Type | Required | Description | | --- | --- | --- | --- | -| `namespace` | `string` | No | Name of the namespace to operate in. Defaults to `default`. | +| `namespace` | `string` | No | Name of the namespace to operate in. | ## Request Body @@ -46,10 +47,10 @@ Content type: `application/json`. | Field | Type | Required | Description | | --- | --- | --- | --- | -| `name` | `string` | Yes | Name of the actor as registered in your RivetKit registry. 1 to 64 bytes. | +| `name` | `string` | Yes | Name of the actor as registered in your RivetKit registry. | | `key` | `string \| null` | No | Key identifying this actor within its name. Multi-part keys are joined with `/`, see [Actor Keys](/docs/api/actor-keys). | -| `input` | `string \| null` | No | Input passed to the actor if this request creates it, encoded as standard base64 (not base64url). | -| `runner_name_selector` | `string \| null` | No | Node pool that runs the actor. Defaults to `default`. | +| `input` | `string \| null` | No | Base64url-encoded CBOR input passed to the actor's `createState` and `onCreate` hooks when the actor is created. | +| `pool` | `string \| null` | No | Name of the node pool to run the actor in. Defaults to `default`. | ## Responses @@ -62,9 +63,9 @@ The existing or created actor. | `actor` | `object` | | | `actor.actor_id` | `string` | Unique ID of the actor. | | `actor.name` | `string` | Actor name as registered in your RivetKit registry. | -| `actor.key` | `string` | Actor key. Multi-part keys are joined with `/`, see [Actor Keys](/docs/api/actor-keys). An empty string for an actor without a key. | +| `actor.key` | `string` | Actor key. Multi-part keys are joined with `/`, see [Actor Keys](/docs/api/actor-keys). | | `actor.namespace` | `string` | Name of the namespace the actor belongs to. | -| `actor.runner_name_selector` | `string` | Node pool the actor runs in. | +| `actor.pool` | `string` | Name of the node pool the actor runs in. | | `actor.create_ts` | `integer` | When the actor was created, in Unix milliseconds. | | `actor.start_ts` | `integer \| null` | When the actor first started. Not recorded by this version, so always `null`. | | `actor.pending_allocation_ts` | `integer \| null` | When the actor started waiting for a node. Not recorded by this version, so always `null`. | @@ -81,7 +82,7 @@ The existing or created actor. "name": "my-actor", "key": "my-key", "namespace": "my-namespace", - "runner_name_selector": "default", + "pool": "default", "create_ts": 1700000000000, "start_ts": null, "pending_allocation_ts": null, @@ -96,7 +97,7 @@ The existing or created actor. ### 400 -`actor.invalid_name`: `name` is empty or longer than 64 bytes. `actor.invalid_key`: `key` is longer than 1024 bytes. `actor.invalid_key_encoding`: `key` is not in canonical slash-separated form. `actor.key_owned_elsewhere`: another datacenter owns the key. `envoy.invalid_pool_name`: `runner_name_selector` is not a valid pool name. `envoy.invalid_namespace_name`: the `namespace` value is not a DNS label of 1 to 63 lowercase letters, digits and hyphens. +`actor.invalid_name`: `name` is empty or longer than 64 bytes. `actor.invalid_key`: `key` is longer than 1024 bytes. `actor.invalid_key_encoding`: `key` is not in canonical slash-separated form. `actor.key_owned_elsewhere`: another datacenter owns the key. `envoy.invalid_pool_name`: `pool` is not a valid pool name. `envoy.invalid_namespace_name`: the `namespace` value is not a DNS label of 1 to 63 lowercase letters, digits and hyphens. | Field | Type | Description | | --- | --- | --- | diff --git a/vendor/api/docs/content/actors/get.mdx b/vendor/api/docs/content/actors/get.mdx deleted file mode 100644 index ced55eba..00000000 --- a/vendor/api/docs/content/actors/get.mdx +++ /dev/null @@ -1,194 +0,0 @@ ---- -title: "Get Actor" -description: "Get a live actor by ID." ---- - -{/* Generated by scripts/docs/gen-api-reference.mjs from engine/artifacts/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} - -Returns `actor.not_found` for an actor that was destroyed or belongs to another namespace. A namespace token needs a grant on `actor` with `read`. - -```http -GET https://rivet.example.com/actors/{actor_id} -``` - -## Examples - - - -```bash cURL -curl "https://rivet.example.com/actors/$ACTOR_ID?namespace=$RIVET_NAMESPACE" \ - -H "Authorization: Bearer $RIVET_TOKEN" -``` - - - -## Authentication - -Send the admin token, or a namespace token from [Create Token](/docs/api/tokens/create) whose grants cover the request, as a bearer token in the `Authorization` header. The `x-rivet-token` header is also accepted. Routes with a `namespace` query parameter use the `default` namespace when it is omitted. See [Authentication](/docs/api/authentication). - -## Path Parameters - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `actor_id` | `string` | Yes | ID of the actor. | - -## Query Parameters - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `namespace` | `string` | No | Name of the namespace to operate in. Defaults to `default`. | - -## Responses - -### 200 - -The actor. - -| Field | Type | Description | -| --- | --- | --- | -| `actor` | `object` | | -| `actor.actor_id` | `string` | Unique ID of the actor. | -| `actor.name` | `string` | Actor name as registered in your RivetKit registry. | -| `actor.key` | `string` | Actor key. Multi-part keys are joined with `/`, see [Actor Keys](/docs/api/actor-keys). An empty string for an actor without a key. | -| `actor.namespace` | `string` | Name of the namespace the actor belongs to. | -| `actor.runner_name_selector` | `string` | Node pool the actor runs in. | -| `actor.create_ts` | `integer` | When the actor was created, in Unix milliseconds. | -| `actor.start_ts` | `integer \| null` | When the actor first started. Not recorded by this version, so always `null`. | -| `actor.pending_allocation_ts` | `integer \| null` | When the actor started waiting for a node. Not recorded by this version, so always `null`. | -| `actor.connectable_ts` | `integer \| null` | When the actor last became connectable. Not recorded by this version, so always `null`. | -| `actor.sleep_ts` | `integer \| null` | When the actor went to sleep. Not recorded by this version, so always `null`. | -| `actor.reschedule_ts` | `integer \| null` | When the actor will next try to allocate. Not recorded by this version, so always `null`. | -| `actor.destroy_ts` | `integer \| null` | When the actor was destroyed, in Unix milliseconds. Only set in listings that include destroyed actors; otherwise `null`. | - -```json -{ - "actor": { - "actor_id": "d97pbq1nyqxw1w5qdwz0iirbqiblh2", - "name": "my-actor", - "key": "my-key", - "namespace": "my-namespace", - "runner_name_selector": "default", - "create_ts": 1700000000000, - "start_ts": null, - "pending_allocation_ts": null, - "connectable_ts": null, - "sleep_ts": null, - "reschedule_ts": null, - "destroy_ts": null - } -} -``` - -### 400 - -`envoy.invalid_namespace_name`: the `namespace` value is not a DNS label of 1 to 63 lowercase letters, digits and hyphens. - -| Field | Type | Description | -| --- | --- | --- | -| `group` | `string` | Error group, for example `actor`. | -| `code` | `string` | Error code within the group, for example `not_found`. | -| `message` | `string` | Human-readable error message. | -| `metadata` | `any` | Extra details. Only present on some errors raised while authenticating or authorizing the request. | - -```json -{ - "group": "envoy", - "code": "invalid_namespace_name", - "message": "Namespace name must be a DNS label of 1 to 63 lowercase letters, digits and hyphens." -} -``` - -### 401 - -`auth.invalid_token`: the request carries no token, or the token is not valid. `auth.token_expired`: the token has expired. - -| Field | Type | Description | -| --- | --- | --- | -| `group` | `string` | Error group, for example `actor`. | -| `code` | `string` | Error code within the group, for example `not_found`. | -| `message` | `string` | Human-readable error message. | -| `metadata` | `any` | Extra details. Only present on some errors raised while authenticating or authorizing the request. | - -```json -{ - "group": "auth", - "code": "invalid_token", - "message": "Authentication token is invalid." -} -``` - -### 403 - -`auth.insufficient_permissions`: the token's grants do not cover this request. For a namespace token this is also returned when the actor does not exist. - -| Field | Type | Description | -| --- | --- | --- | -| `group` | `string` | Error group, for example `actor`. | -| `code` | `string` | Error code within the group, for example `not_found`. | -| `message` | `string` | Human-readable error message. | -| `metadata` | `any` | Extra details. Only present on some errors raised while authenticating or authorizing the request. | - -```json -{ - "group": "auth", - "code": "insufficient_permissions", - "message": "Insufficient permissions to access this resource." -} -``` - -### 404 - -`actor.not_found`: the actor does not exist, was destroyed, or belongs to another namespace. `namespace.not_found`: the namespace does not exist. - -| Field | Type | Description | -| --- | --- | --- | -| `group` | `string` | Error group, for example `actor`. | -| `code` | `string` | Error code within the group, for example `not_found`. | -| `message` | `string` | Human-readable error message. | -| `metadata` | `any` | Extra details. Only present on some errors raised while authenticating or authorizing the request. | - -```json -{ - "group": "actor", - "code": "not_found", - "message": "The actor does not exist or was destroyed." -} -``` - -### 500 - -`core.internal_error`: an unexpected failure, including an `actor_id` that is not a valid Rivet ID. - -| Field | Type | Description | -| --- | --- | --- | -| `group` | `string` | Error group, for example `actor`. | -| `code` | `string` | Error code within the group, for example `not_found`. | -| `message` | `string` | Human-readable error message. | -| `metadata` | `any` | Extra details. Only present on some errors raised while authenticating or authorizing the request. | - -```json -{ - "group": "core", - "code": "internal_error", - "message": "An internal error occurred" -} -``` - -### 503 - -`auth.verification_unavailable`: token verification keys are temporarily unavailable. Retry the request. - -| Field | Type | Description | -| --- | --- | --- | -| `group` | `string` | Error group, for example `actor`. | -| `code` | `string` | Error code within the group, for example `not_found`. | -| `message` | `string` | Human-readable error message. | -| `metadata` | `any` | Extra details. Only present on some errors raised while authenticating or authorizing the request. | - -```json -{ - "group": "auth", - "code": "verification_unavailable", - "message": "The server could not verify the authentication token because verification keys are temporarily unavailable. Retry the request." -} -``` diff --git a/vendor/api/docs/content/actors/list-names.mdx b/vendor/api/docs/content/actors/list-names.mdx index 81974f0a..26c8134b 100644 --- a/vendor/api/docs/content/actors/list-names.mdx +++ b/vendor/api/docs/content/actors/list-names.mdx @@ -1,12 +1,10 @@ --- title: "List Actor Names" -description: "List the actor names that the namespace's connected nodes accept." +description: "List the distinct actor names that have been created in a namespace." --- {/* Generated by scripts/docs/gen-api-reference.mjs from engine/artifacts/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} -A namespace token needs a grant on `actor` with `list`. - ```http GET https://rivet.example.com/actors/names ``` @@ -26,19 +24,19 @@ curl "https://rivet.example.com/actors/names?namespace=$RIVET_NAMESPACE" \ ## Authentication -Send the admin token, or a namespace token from [Create Token](/docs/api/tokens/create) whose grants cover the request, as a bearer token in the `Authorization` header. The `x-rivet-token` header is also accepted. Routes with a `namespace` query parameter use the `default` namespace when it is omitted. See [Authentication](/docs/api/authentication). +Send your namespace token as a bearer token in the `Authorization` header. Every control plane request also requires the `namespace` query parameter. See [Authentication](/docs/api/authentication). ## Query Parameters | Name | Type | Required | Description | | --- | --- | --- | --- | -| `namespace` | `string` | No | Name of the namespace to operate in. Defaults to `default`. | +| `namespace` | `string` | No | Name of the namespace to operate in. | ## Responses ### 200 -Map of actor name to metadata. +The actor names. | Field | Type | Description | | --- | --- | --- | diff --git a/vendor/api/docs/content/actors/list.mdx b/vendor/api/docs/content/actors/list.mdx index 5ca3fdb1..5f777403 100644 --- a/vendor/api/docs/content/actors/list.mdx +++ b/vendor/api/docs/content/actors/list.mdx @@ -1,11 +1,11 @@ --- title: "List Actors" -description: "List actors in a namespace by ID, by name and key, or by name. Listings by name are paginated." +description: "List actors in a namespace, optionally filtered by name, key, or ID. Results are paginated." --- {/* Generated by scripts/docs/gen-api-reference.mjs from engine/artifacts/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} -Pass `actor_ids` (comma-separated) to look up actors by ID, or `name` with an optional `key`. `actor_ids` takes precedence over `name` and `key`. Only a listing by `name` without `key` is paginated; a page can hold fewer than `limit` actors while `pagination.cursor` is still set. Destroyed actors are excluded unless `include_destroyed` is `true`. A namespace token needs a grant on `actor` with `list`. +`key` requires `name`. `actor_id` cannot be combined with `name` or `key`. Destroyed actors are excluded unless `include_destroyed` is `true`. ```http GET https://rivet.example.com/actors @@ -26,19 +26,19 @@ curl "https://rivet.example.com/actors?namespace=$RIVET_NAMESPACE&name=counter" ## Authentication -Send the admin token, or a namespace token from [Create Token](/docs/api/tokens/create) whose grants cover the request, as a bearer token in the `Authorization` header. The `x-rivet-token` header is also accepted. Routes with a `namespace` query parameter use the `default` namespace when it is omitted. See [Authentication](/docs/api/authentication). +Send your namespace token as a bearer token in the `Authorization` header. Every control plane request also requires the `namespace` query parameter. See [Authentication](/docs/api/authentication). ## Query Parameters | Name | Type | Required | Description | | --- | --- | --- | --- | -| `namespace` | `string` | No | Name of the namespace to operate in. Defaults to `default`. | -| `name` | `string` | No | Only return actors with this name. Required unless `actor_ids` or `actor_id` is set. | +| `namespace` | `string` | No | Name of the namespace to operate in. | +| `name` | `string` | No | Only return actors with this name. | | `key` | `string` | No | Only return the actor with this key. Requires `name`. Multi-part keys are joined with `/`, see [Actor Keys](/docs/api/actor-keys). | -| `actor_ids` | `string` | No | Comma-separated IDs of the actors to return. | -| `actor_id` | `string` | No | Same as `actor_ids`. Used only when `actor_ids` is absent. | -| `include_destroyed` | `boolean` | No | Include destroyed actors. Must be `true` or `false`. | -| `limit` | `integer` | No | Maximum number of results to return, from 1 to 100. Defaults to 100. | +| `actor_ids` | `string` | No | Deprecated. Use `actor_id` instead. | +| `actor_id` | `string` | No | Only return actors with these IDs. Repeat the parameter for multiple IDs. | +| `include_destroyed` | `boolean` | No | Include actors that have been destroyed. | +| `limit` | `integer` | No | Maximum number of results to return. | | `cursor` | `string` | No | Pagination cursor. Pass the `pagination.cursor` value from the previous response to fetch the next page. | ## Responses @@ -52,9 +52,9 @@ Matching actors and a cursor for the next page. `pagination.cursor` is `null` on | `actors` | `object[]` | | | `actors[].actor_id` | `string` | Unique ID of the actor. | | `actors[].name` | `string` | Actor name as registered in your RivetKit registry. | -| `actors[].key` | `string` | Actor key. Multi-part keys are joined with `/`, see [Actor Keys](/docs/api/actor-keys). An empty string for an actor without a key. | +| `actors[].key` | `string` | Actor key. Multi-part keys are joined with `/`, see [Actor Keys](/docs/api/actor-keys). | | `actors[].namespace` | `string` | Name of the namespace the actor belongs to. | -| `actors[].runner_name_selector` | `string` | Node pool the actor runs in. | +| `actors[].pool` | `string` | Name of the node pool the actor runs in. | | `actors[].create_ts` | `integer` | When the actor was created, in Unix milliseconds. | | `actors[].start_ts` | `integer \| null` | When the actor first started. Not recorded by this version, so always `null`. | | `actors[].pending_allocation_ts` | `integer \| null` | When the actor started waiting for a node. Not recorded by this version, so always `null`. | @@ -73,7 +73,7 @@ Matching actors and a cursor for the next page. `pagination.cursor` is `null` on "name": "my-actor", "key": "my-key", "namespace": "my-namespace", - "runner_name_selector": "default", + "pool": "default", "create_ts": 1700000000000, "start_ts": null, "pending_allocation_ts": null, diff --git a/vendor/api/docs/content/actors/reschedule.mdx b/vendor/api/docs/content/actors/reschedule.mdx index da874ed2..b7e78498 100644 --- a/vendor/api/docs/content/actors/reschedule.mdx +++ b/vendor/api/docs/content/actors/reschedule.mdx @@ -1,12 +1,10 @@ --- title: "Reschedule Actor" -description: "Move an actor to a new allocation. A running actor is stopped and starts again, possibly on another node, with its persisted state." +description: "Move an actor to a different worker. The actor runs its shutdown sequence, then restarts elsewhere with its persisted state." --- {/* Generated by scripts/docs/gen-api-reference.mjs from engine/artifacts/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} -A running or stopping actor is stopped and allocated again, and a sleeping actor is allocated now. An actor that is still starting, or is destroyed, is left as is and the request still succeeds. The request body is ignored. A namespace token needs a grant on `actor` with `update`. - ```http POST https://rivet.example.com/actors/{actor_id}/reschedule ``` @@ -26,7 +24,7 @@ curl -X POST "https://rivet.example.com/actors/$ACTOR_ID/reschedule?namespace=$R ## Authentication -Send the admin token, or a namespace token from [Create Token](/docs/api/tokens/create) whose grants cover the request, as a bearer token in the `Authorization` header. The `x-rivet-token` header is also accepted. Routes with a `namespace` query parameter use the `default` namespace when it is omitted. See [Authentication](/docs/api/authentication). +Send your namespace token as a bearer token in the `Authorization` header. Every control plane request also requires the `namespace` query parameter. See [Authentication](/docs/api/authentication). ## Path Parameters @@ -38,13 +36,13 @@ Send the admin token, or a namespace token from [Create Token](/docs/api/tokens/ | Name | Type | Required | Description | | --- | --- | --- | --- | -| `namespace` | `string` | No | Name of the namespace to operate in. Defaults to `default`. | +| `namespace` | `string` | No | Name of the namespace to operate in. | ## Responses ### 200 -The reschedule was accepted, or there was nothing to move. The response body is an empty object. +The reschedule was accepted, or there was nothing to move. ```json {} diff --git a/vendor/api/docs/content/actors/sleep.mdx b/vendor/api/docs/content/actors/sleep.mdx index b3adae65..84015757 100644 --- a/vendor/api/docs/content/actors/sleep.mdx +++ b/vendor/api/docs/content/actors/sleep.mdx @@ -5,8 +5,6 @@ description: "Put an actor to sleep. The actor runs its shutdown sequence and pe {/* Generated by scripts/docs/gen-api-reference.mjs from engine/artifacts/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} -The request body is ignored. A namespace token needs a grant on `actor` with `update`. - ```http POST https://rivet.example.com/actors/{actor_id}/sleep ``` @@ -26,7 +24,7 @@ curl -X POST "https://rivet.example.com/actors/$ACTOR_ID/sleep?namespace=$RIVET_ ## Authentication -Send the admin token, or a namespace token from [Create Token](/docs/api/tokens/create) whose grants cover the request, as a bearer token in the `Authorization` header. The `x-rivet-token` header is also accepted. Routes with a `namespace` query parameter use the `default` namespace when it is omitted. See [Authentication](/docs/api/authentication). +Send your namespace token as a bearer token in the `Authorization` header. Every control plane request also requires the `namespace` query parameter. See [Authentication](/docs/api/authentication). ## Path Parameters @@ -38,13 +36,13 @@ Send the admin token, or a namespace token from [Create Token](/docs/api/tokens/ | Name | Type | Required | Description | | --- | --- | --- | --- | -| `namespace` | `string` | No | Name of the namespace to operate in. Defaults to `default`. | +| `namespace` | `string` | No | Name of the namespace to operate in. | ## Responses ### 200 -The sleep was accepted. The response body is an empty object. +The sleep was accepted. ```json {} diff --git a/vendor/api/docs/content/authentication.mdx b/vendor/api/docs/content/authentication.mdx index cdb0ade7..5a7d27c3 100644 --- a/vendor/api/docs/content/authentication.mdx +++ b/vendor/api/docs/content/authentication.mdx @@ -81,7 +81,7 @@ const ws = new WebSocket( ); ``` -The inline `{actor_id}@{token}` path form and the `rvt-token` query parameter also work on gateway WebSockets, and are simpler for clients that cannot set subprotocols. This applies to [Raw WebSocket](/docs/api/websockets), [Connect](/docs/api/gateway/connect), [Inspector Connect](/docs/api/inspector-connect), and [Node Connection](/docs/api/worker-connect). +The inline `{actor_id}@{token}` path form and the `rvt-token` query parameter also work on gateway WebSockets, and are simpler for clients that cannot set subprotocols. This applies to [Raw WebSocket](/docs/api/websockets), [Connect](/docs/api/gateway/connect), and [Node Connection](/docs/api/worker-connect). ## Control Plane Requests diff --git a/vendor/api/docs/content/control-plane/datacenters.mdx b/vendor/api/docs/content/control-plane/datacenters.mdx index 87f64dfa..bdc57c24 100644 --- a/vendor/api/docs/content/control-plane/datacenters.mdx +++ b/vendor/api/docs/content/control-plane/datacenters.mdx @@ -5,8 +5,6 @@ description: "List the datacenters configured for the control plane." {/* Generated by scripts/docs/gen-api-reference.mjs from engine/artifacts/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} -A namespace token needs a grant on `datacenter` with `list`. - ```http GET https://rivet.example.com/datacenters ``` @@ -26,13 +24,13 @@ curl "https://rivet.example.com/datacenters" \ ## Authentication -Send the admin token, or a namespace token from [Create Token](/docs/api/tokens/create) whose grants cover the request, as a bearer token in the `Authorization` header. The `x-rivet-token` header is also accepted. Routes with a `namespace` query parameter use the `default` namespace when it is omitted. See [Authentication](/docs/api/authentication). +Send your namespace token as a bearer token in the `Authorization` header. Every control plane request also requires the `namespace` query parameter. See [Authentication](/docs/api/authentication). ## Responses ### 200 -Configured datacenters. +Configured datacenters and an empty pagination cursor. | Field | Type | Description | | --- | --- | --- | diff --git a/vendor/api/docs/content/control-plane/metadata.mdx b/vendor/api/docs/content/control-plane/metadata.mdx index ff17f1d3..fcdd2fde 100644 --- a/vendor/api/docs/content/control-plane/metadata.mdx +++ b/vendor/api/docs/content/control-plane/metadata.mdx @@ -1,11 +1,11 @@ --- title: "Get Metadata" -description: "Get the runtime and version of the control plane." +description: "Get build, runtime, compiler, and fleet protocol metadata for the control plane." --- {/* Generated by scripts/docs/gen-api-reference.mjs from engine/artifacts/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} -A request made with the admin token also receives `actorNames`. +The protocol versions are the versions agreed on by the fleet, which can differ from the versions compiled into the responding node. ```http GET https://rivet.example.com/metadata @@ -31,7 +31,7 @@ No authentication is required. ### 200 -Runtime and version metadata. +Build and protocol metadata for the responding node and its fleet. | Field | Type | Description | | --- | --- | --- | diff --git a/vendor/api/docs/content/gateway/request.mdx b/vendor/api/docs/content/gateway/request.mdx deleted file mode 100644 index 58de2dff..00000000 --- a/vendor/api/docs/content/gateway/request.mdx +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: "Raw HTTP Request" -description: "Forward a raw HTTP request to an actor's onRequest handler. The method, headers, body, and the path after /request/ are passed through unchanged." ---- - -{/* Generated by scripts/docs/gen-api-reference.mjs from rivetkit-openapi/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} - -Use this when an actor exposes its own HTTP routes, streams responses (for example Server-Sent Events), or needs to accept non-JSON payloads. The response is whatever the actor's `onRequest` handler returns. - -```http -ANY https://rivet.example.com/gateway/{actor}/request/{path} -``` - -Accepts `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `OPTIONS`. - -## Examples - - - -```bash cURL -curl -X POST "https://rivet.example.com/gateway/counter/request/increment?rvt-namespace=$RIVET_NAMESPACE&rvt-method=getOrCreate&rvt-key=my-counter&rvt-pool=default" \ - -H "x-rivet-token: $RIVET_TOKEN" -``` - - - - - -## Authentication - -Send a token in the `x-rivet-token` header, inline in the path as `{actor_id}@{token}`, or in the `rvt-token` query parameter. Use a [scoped token](/docs/jwt) from browsers and your Rivet token from trusted backends. See [Authentication](/docs/api/authentication). - -## Path Parameters - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `actor` | `string` | Yes | Actor ID, actor ID with an inline token (`{actor_id}@{token}`), or actor name combined with the `rvt-*` query parameters. | -| `path` | `string` | Yes | Path forwarded to the actor. The actor sees a request whose URL path is `/{path}`. | - -## Actor Selector - -`{actor}` accepts an actor ID, an actor ID with an inline routing token (`{actor_id}@{token}`), or an actor name combined with the `rvt-*` query parameters below. See [Actor Routing](/docs/api/actor-routing) for the full rules. - - - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `rvt-namespace` | `string` | No | Namespace the actor lives in. Required when `{actor}` is an actor name. | -| `rvt-method` | `string` | No | How to resolve an actor name to an actor. `getOrCreate` requires `rvt-pool`. One of `"get"`, `"getOrCreate"`. | -| `rvt-key` | `string` | No | Actor key. Separate multi-part keys with commas. | -| `rvt-pool` | `string` | No | Pool to create the actor on when `rvt-method=getOrCreate`. RivetKit registers the `default` pool unless configured otherwise. | -| `rvt-runner` | `string` | No | Deprecated alias for `rvt-pool`. | -| `rvt-input` | `string` | No | Base64url-encoded CBOR input passed to `createState` and `onCreate` when `rvt-method=getOrCreate` creates the actor. | -| `rvt-region` | `string` | No | Preferred region when `rvt-method=getOrCreate` creates the actor. | -| `rvt-crash-policy` | `string` | No | Crash policy when `rvt-method=getOrCreate` creates the actor. RivetKit defaults to `sleep`. One of `"restart"`, `"sleep"`, `"destroy"`. | -| `rvt-skip-ready-wait` | `boolean` | No | Return as soon as the actor is resolved instead of waiting for it to be ready. | -| `rvt-token` | `string` | No | Token to authenticate with. Prefer the `x-rivet-token` header or inline path token when possible. | - - - -## Responses - -### 200 - -The response returned by the actor's `onRequest` handler. - -## Related - -- [Low-Level HTTP Handler](/actors/docs/request-handler) -- [Raw WebSocket](/docs/api/websockets) diff --git a/vendor/api/docs/content/index.mdx b/vendor/api/docs/content/index.mdx index 59f7975c..f03aeb40 100644 --- a/vendor/api/docs/content/index.mdx +++ b/vendor/api/docs/content/index.mdx @@ -10,7 +10,7 @@ Everything the RivetKit client does happens over HTTP. This reference documents https://rivet.example.com ``` -Self-hosted deployments use the endpoint from your `RIVET_ENDPOINT` URL instead. See [Endpoints](/docs/connect). +Self-hosted deployments use the endpoint from your `RIVET_ENDPOINT` URL instead. See [Endpoints](/docs/endpoints). ## Two Surfaces @@ -42,7 +42,6 @@ Most applications only need the gateway. The RivetKit client resolves actors by ## When to Use HTTP Directly - Calling actors from a language without a RivetKit client (Go, Ruby, PHP, shell scripts). -- Serverless platforms or edge runtimes where you want zero dependencies. - Operational scripts that list, destroy, or sleep actors in bulk. - Debugging: reproducing what the client sends with curl. diff --git a/vendor/api/docs/content/inspector-connect.mdx b/vendor/api/docs/content/inspector-connect.mdx deleted file mode 100644 index 00f700ae..00000000 --- a/vendor/api/docs/content/inspector-connect.mdx +++ /dev/null @@ -1,525 +0,0 @@ ---- -title: "Inspector Connect" -description: "Open the Inspector WebSocket used for live actor inspection." ---- - - -The inspector API is subject to change without notice. Do not build production integrations on it. - - -The inspector connection streams live data about one actor. `{actor}` is an actor ID. See [Actor Routing](/docs/api/actor-routing). - -```http -GET wss://rivet.example.com/gateway/{actor}/inspector/connect?protocol_version=6 -``` - -## Handshake - -Pass these WebSocket subprotocols in this order: - -| Subprotocol | Purpose | -| --- | --- | -| `rivet` | Selects the Rivet WebSocket protocol. | -| `rivet_target.actor` | Routes the connection to an actor. | -| `rivet_actor.{actor}` | Identifies the actor. | -| `rivet_encoding.bare` | Selects BARE binary messages. | -| `rivet_token.{token}` | Authenticates the gateway request. | -| `rivet_inspector_token.{token}` | Authenticates access to the inspector. | - -{/* TODO(code): document how to read an Actor's inspector token once an API returns it (ACT-6493). */} - -Set `protocol_version=6` for the message shapes on this page. Supported values are `1` through `6`. Omitting the parameter selects the legacy version 5 framing, which embeds a version in every message. - - - -```javascript Raw WebSocket -import * as cbor from "cbor-x"; -import { - CURRENT_VERSION, - TO_CLIENT_VERSIONED, - TO_SERVER_VERSIONED, -} from "rivetkit/inspector/client"; - -const ws = new WebSocket( - `wss://rivet.example.com/gateway/${actorId}/inspector/connect?protocol_version=${CURRENT_VERSION}`, - [ - "rivet", - "rivet_target.actor", - `rivet_actor.${actorId}`, - "rivet_encoding.bare", - `rivet_token.${apiToken}`, - `rivet_inspector_token.${inspectorToken}`, - ], -); -ws.binaryType = "arraybuffer"; - -ws.onmessage = (event) => { - const message = TO_CLIENT_VERSIONED.deserialize( - new Uint8Array(event.data), - CURRENT_VERSION, - ); - if (message.body.tag === "StateUpdated") { - console.log(cbor.decode(new Uint8Array(message.body.val.state))); - } - console.log(message.body); -}; - -ws.onopen = () => { - ws.send(TO_SERVER_VERSIONED.serialize({ - body: { tag: "StateRequest", val: { id: 1n } }, - }, CURRENT_VERSION)); -}; -``` - - - -## Message envelope - -Messages are binary BARE frames, not JSON text. Import the versioned codecs from `rivetkit/inspector/client` as shown above. The decoded envelope is `{ body: { tag, val } }`. Fields with type `data` contain CBOR bytes. Decode those bytes with a CBOR codec. The JSON examples below show the decoded logical shape, with CBOR values expanded for readability. Unsigned integers decode to JavaScript `bigint`. - -Most requests have a client-selected `id`. Their response uses the same value as `rid`. `PatchStateRequest` has no response. - -## Client to actor messages - -### PatchStateRequest - -Replaces the actor state. - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `state` | `data` | Yes | New state encoded as CBOR. | - -```json -{ "body": { "tag": "PatchStateRequest", "val": { "state": { "count": 2 } } } } -``` - -### StateRequest - -Requests the current state. - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `id` | `uint` | Yes | Request identifier. | - -```json -{ "body": { "tag": "StateRequest", "val": { "id": 1 } } } -``` - -### ConnectionsRequest - -Requests the current connections. - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `id` | `uint` | Yes | Request identifier. | - -```json -{ "body": { "tag": "ConnectionsRequest", "val": { "id": 2 } } } -``` - -### ActionRequest - -Calls an actor action. - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `id` | `uint` | Yes | Request identifier. | -| `name` | `string` | Yes | Action name. | -| `args` | `data` | Yes | Action arguments encoded as CBOR. | - -```json -{ "body": { "tag": "ActionRequest", "val": { "id": 3, "name": "increment", "args": [1] } } } -``` - -### RpcsListRequest - -Requests the available action names. - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `id` | `uint` | Yes | Request identifier. | - -```json -{ "body": { "tag": "RpcsListRequest", "val": { "id": 4 } } } -``` - -### TraceQueryRequest - -Queries traces in a time range. - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `id` | `uint` | Yes | Request identifier. | -| `startMs` | `uint` | Yes | Inclusive start time in Unix milliseconds. | -| `endMs` | `uint` | Yes | End time in Unix milliseconds. | -| `limit` | `uint` | Yes | Maximum number of records. | - -```json -{ "body": { "tag": "TraceQueryRequest", "val": { "id": 5, "startMs": 1735689600000, "endMs": 1735689660000, "limit": 100 } } } -``` - -### QueueRequest - -Requests queue status. The actor limits `limit` to 200. - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `id` | `uint` | Yes | Request identifier. | -| `limit` | `uint` | Yes | Maximum number of message summaries. | - -```json -{ "body": { "tag": "QueueRequest", "val": { "id": 6, "limit": 50 } } } -``` - -### WorkflowHistoryRequest - -Requests workflow history. - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `id` | `uint` | Yes | Request identifier. | - -```json -{ "body": { "tag": "WorkflowHistoryRequest", "val": { "id": 7 } } } -``` - -### WorkflowReplayRequest - -Replays a workflow from an optional history entry. - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `id` | `uint` | Yes | Request identifier. | -| `entryId` | `string` | No | History entry to replay from. `null` starts from the beginning. | - -```json -{ "body": { "tag": "WorkflowReplayRequest", "val": { "id": 8, "entryId": "step-2" } } } -``` - -### DatabaseSchemaRequest - -Requests the SQLite schema. - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `id` | `uint` | Yes | Request identifier. | - -```json -{ "body": { "tag": "DatabaseSchemaRequest", "val": { "id": 9 } } } -``` - -### DatabaseTableRowsRequest - -Requests rows from a SQLite table. - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `id` | `uint` | Yes | Request identifier. | -| `table` | `string` | Yes | Table name. | -| `limit` | `uint` | Yes | Maximum rows to return. | -| `offset` | `uint` | Yes | Number of rows to skip. | - -```json -{ "body": { "tag": "DatabaseTableRowsRequest", "val": { "id": 10, "table": "users", "limit": 50, "offset": 0 } } } -``` - -### SchedulesRequest - -Requests all schedules. - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `id` | `uint` | Yes | Request identifier. | - -```json -{ "body": { "tag": "SchedulesRequest", "val": { "id": 11 } } } -``` - -### ScheduleHistoryRequest - -Requests recent fires for one schedule. - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `id` | `uint` | Yes | Request identifier. | -| `scheduleId` | `string` | Yes | Schedule identifier. | -| `limit` | `uint` | Yes | Maximum history entries. | - -```json -{ "body": { "tag": "ScheduleHistoryRequest", "val": { "id": 12, "scheduleId": "cleanup", "limit": 20 } } } -``` - -### ScheduleDeleteRequest - -Deletes a schedule. - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `id` | `uint` | Yes | Request identifier. | -| `scheduleId` | `string` | Yes | Schedule identifier. | -| `kind` | `string` | Yes | Schedule kind: `at`, `cron`, or `every`. | - -```json -{ "body": { "tag": "ScheduleDeleteRequest", "val": { "id": 13, "scheduleId": "cleanup", "kind": "cron" } } } -``` - -## Actor to client messages - -### Init - -Sent when inspection starts. It contains the initial snapshot. - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `connections` | `Connection[]` | Yes | Current connections. Each item has string `id` and CBOR `details`. | -| `state` | `data` | No | Current state encoded as CBOR. | -| `isStateEnabled` | `boolean` | Yes | Whether the actor uses state. | -| `rpcs` | `string[]` | Yes | Available action names. | -| `isDatabaseEnabled` | `boolean` | Yes | Whether SQLite is enabled. | -| `queueSize` | `uint` | Yes | Current queued message count. | -| `workflowHistory` | `data` | No | Workflow history transport data. | -| `isWorkflowEnabled` | `boolean` | Yes | Whether workflows are enabled. | -| `tabConfig` | `TabConfigEntry[]` | Yes | Inspector tabs. Each item has `id`, optional `label`, optional `icon`, and boolean `hidden`. | -| `schedules` | `Schedule[]` | Yes | Current schedules. | - -```json -{ "body": { "tag": "Init", "val": { "connections": [], "state": { "count": 1 }, "isStateEnabled": true, "rpcs": ["increment"], "isDatabaseEnabled": true, "queueSize": 0, "workflowHistory": null, "isWorkflowEnabled": false, "tabConfig": [{ "id": "state", "label": null, "icon": null, "hidden": false }], "schedules": [] } } } -``` - -### StateResponse - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `rid` | `uint` | Yes | Matching request identifier. | -| `state` | `data` | No | State encoded as CBOR. | -| `isStateEnabled` | `boolean` | Yes | Whether state is enabled. | - -```json -{ "body": { "tag": "StateResponse", "val": { "rid": 1, "state": { "count": 2 }, "isStateEnabled": true } } } -``` - -### ConnectionsResponse - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `rid` | `uint` | Yes | Matching request identifier. | -| `connections` | `Connection[]` | Yes | Connections with string `id` and CBOR `details`. | - -```json -{ "body": { "tag": "ConnectionsResponse", "val": { "rid": 2, "connections": [{ "id": "conn-1", "details": { "name": "Sam" } }] } } } -``` - -### ActionResponse - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `rid` | `uint` | Yes | Matching request identifier. | -| `output` | `data` | Yes | Action output encoded as CBOR. | - -```json -{ "body": { "tag": "ActionResponse", "val": { "rid": 3, "output": 2 } } } -``` - -### RpcsListResponse - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `rid` | `uint` | Yes | Matching request identifier. | -| `rpcs` | `string[]` | Yes | Available action names. | - -```json -{ "body": { "tag": "RpcsListResponse", "val": { "rid": 4, "rpcs": ["increment"] } } } -``` - -### TraceQueryResponse - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `rid` | `uint` | Yes | Matching request identifier. | -| `payload` | `data` | Yes | Trace range transport payload. | - -```json -{ "body": { "tag": "TraceQueryResponse", "val": { "rid": 5, "payload": { "records": [] } } } } -``` - -### QueueResponse - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `rid` | `uint` | Yes | Matching request identifier. | -| `status.size` | `uint` | Yes | Current queue size. | -| `status.maxSize` | `uint` | Yes | Queue capacity. | -| `status.messages` | `QueueMessageSummary[]` | Yes | Summaries with uint `id`, string `name`, and uint `createdAtMs`. | -| `status.truncated` | `boolean` | Yes | Whether more summaries were available. | - -```json -{ "body": { "tag": "QueueResponse", "val": { "rid": 6, "status": { "size": 1, "maxSize": 1000, "messages": [{ "id": 42, "name": "email", "createdAtMs": 1735689600000 }], "truncated": false } } } } -``` - -### WorkflowHistoryResponse - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `rid` | `uint` | Yes | Matching request identifier. | -| `history` | `data` | No | Workflow history transport data. | -| `isWorkflowEnabled` | `boolean` | Yes | Whether workflows are enabled. | - -```json -{ "body": { "tag": "WorkflowHistoryResponse", "val": { "rid": 7, "history": null, "isWorkflowEnabled": false } } } -``` - -### WorkflowReplayResponse - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `rid` | `uint` | Yes | Matching request identifier. | -| `history` | `data` | No | Updated workflow history transport data. | -| `isWorkflowEnabled` | `boolean` | Yes | Whether workflows are enabled. | - -```json -{ "body": { "tag": "WorkflowReplayResponse", "val": { "rid": 8, "history": { "entries": [] }, "isWorkflowEnabled": true } } } -``` - -### DatabaseSchemaResponse - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `rid` | `uint` | Yes | Matching request identifier. | -| `schema` | `data` | Yes | SQLite schema encoded as CBOR. | - -```json -{ "body": { "tag": "DatabaseSchemaResponse", "val": { "rid": 9, "schema": { "tables": [] } } } } -``` - -### DatabaseTableRowsResponse - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `rid` | `uint` | Yes | Matching request identifier. | -| `result` | `data` | Yes | Rows encoded as CBOR. | - -```json -{ "body": { "tag": "DatabaseTableRowsResponse", "val": { "rid": 10, "result": [{ "id": 1 }] } } } -``` - -### SchedulesResponse - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `rid` | `uint` | Yes | Matching request identifier. | -| `schedules` | `Schedule[]` | Yes | Current schedules. | - -```json -{ "body": { "tag": "SchedulesResponse", "val": { "rid": 11, "schedules": [] } } } -``` - -### ScheduleHistoryResponse - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `rid` | `uint` | Yes | Matching request identifier. | -| `scheduleId` | `string` | Yes | Schedule identifier. | -| `history` | `ScheduleFire[]` | Yes | Schedule fire history. | - -```json -{ "body": { "tag": "ScheduleHistoryResponse", "val": { "rid": 12, "scheduleId": "cleanup", "history": [{ "action": "cleanup", "scheduledAt": 1735689600000, "firedAt": 1735689600010, "finishedAt": 1735689600040, "result": "ok", "error": null }] } } } -``` - -### ScheduleDeleteResponse - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `rid` | `uint` | Yes | Matching request identifier. | -| `scheduleId` | `string` | Yes | Schedule identifier. | -| `deleted` | `boolean` | Yes | Whether a schedule was deleted. | - -```json -{ "body": { "tag": "ScheduleDeleteResponse", "val": { "rid": 13, "scheduleId": "cleanup", "deleted": true } } } -``` - -### ConnectionsUpdated - -Sent when the connection list changes. - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `connections` | `Connection[]` | Yes | Current connections. | - -```json -{ "body": { "tag": "ConnectionsUpdated", "val": { "connections": [] } } } -``` - -### StateUpdated - -Sent when state changes. - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `state` | `data` | Yes | State encoded as CBOR. | - -```json -{ "body": { "tag": "StateUpdated", "val": { "state": { "count": 3 } } } } -``` - -### QueueUpdated - -Sent when the queue size changes. - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `queueSize` | `uint` | Yes | Current queue size. | - -```json -{ "body": { "tag": "QueueUpdated", "val": { "queueSize": 2 } } } -``` - -### WorkflowHistoryUpdated - -Sent when workflow history changes. - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `history` | `data` | Yes | Workflow history transport data. | - -```json -{ "body": { "tag": "WorkflowHistoryUpdated", "val": { "history": { "entries": [] } } } } -``` - -### SchedulesUpdated - -Sent when schedules change. - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `schedules` | `Schedule[]` | Yes | Current schedules. | - -```json -{ "body": { "tag": "SchedulesUpdated", "val": { "schedules": [] } } } -``` - -### Error - -Reports an inspector protocol error. This message does not carry a request identifier. - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `message` | `string` | Yes | Error identifier or description. | - -```json -{ "body": { "tag": "Error", "val": { "message": "inspector.events_dropped" } } } -``` - -## Shared structures - -`Schedule` contains `id`, optional `name`, `kind`, `action`, CBOR `args`, `nextRunAt`, optional `lastRunAt`, optional `expression`, optional `timezone`, optional `intervalMs`, and optional `maxHistory`. All time and interval values are unsigned integers in milliseconds. - -`ScheduleFire` contains `action`, `scheduledAt`, `firedAt`, optional `finishedAt`, `result`, and optional `error`. An error contains `group`, `code`, `message`, and optional CBOR `metadata`. - -## Close behavior - -An invalid or unsupported `protocol_version` closes the socket with code `1002` and reason `inspector.invalid_protocol_version`. A missing or invalid inspector token closes it with code `1008` and reason `inspector.unauthorized`. Other established-connection errors can arrive as `Error` messages. - -## Related - -- [Actor Routing](/docs/api/actor-routing) -- [Raw WebSocket](/docs/api/websockets) diff --git a/vendor/api/docs/content/inspector/action.mdx b/vendor/api/docs/content/inspector/action.mdx deleted file mode 100644 index 15cf2f22..00000000 --- a/vendor/api/docs/content/inspector/action.mdx +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: "Invoke Action" -description: "Invoke an actor action through the inspector." ---- - -{/* Generated by scripts/docs/gen-api-reference.mjs from rivetkit-openapi/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} - - -The inspector API is subject to change without notice. Do not build production integrations on it. - - -```http -POST https://rivet.example.com/gateway/{actor}/inspector/action/{name} -``` - -## Examples - - - -```bash cURL -curl -X POST "https://rivet.example.com/gateway/$ACTOR_ID/inspector/action/increment" \ - -H "Authorization: Bearer $INSPECTOR_TOKEN" \ - -H "Content-Type: application/json" \ - -d '{ - "args": [ - 1 - ] - }' -``` - - - - - -## Authentication - -Inspector endpoints do not accept namespace tokens. Send the actor's inspector token as a bearer token in the `Authorization` header. {/* TODO(code): document how to read an Actor's inspector token once an API returns it (ACT-6493). */} - -## Path Parameters - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `actor` | `string` | Yes | Actor ID, actor ID with an inline token (`{actor_id}@{token}`), or actor name combined with the `rvt-*` query parameters. | -| `name` | `string` | Yes | Name of the action to invoke. | - -## Headers - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `Authorization` | `string` | No | Bearer token for inspector authentication. Required in production, optional in development. | - -## Actor Selector - -`{actor}` accepts an actor ID, an actor ID with an inline routing token (`{actor_id}@{token}`), or an actor name combined with the `rvt-*` query parameters below. See [Actor Routing](/docs/api/actor-routing) for the full rules. - - - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `rvt-namespace` | `string` | No | Namespace the actor lives in. Required when `{actor}` is an actor name. | -| `rvt-method` | `string` | No | How to resolve an actor name to an actor. `getOrCreate` requires `rvt-pool`. One of `"get"`, `"getOrCreate"`. | -| `rvt-key` | `string` | No | Actor key. Separate multi-part keys with commas. | -| `rvt-pool` | `string` | No | Pool to create the actor on when `rvt-method=getOrCreate`. RivetKit registers the `default` pool unless configured otherwise. | -| `rvt-runner` | `string` | No | Deprecated alias for `rvt-pool`. | -| `rvt-input` | `string` | No | Base64url-encoded CBOR input passed to `createState` and `onCreate` when `rvt-method=getOrCreate` creates the actor. | -| `rvt-region` | `string` | No | Preferred region when `rvt-method=getOrCreate` creates the actor. | -| `rvt-crash-policy` | `string` | No | Crash policy when `rvt-method=getOrCreate` creates the actor. RivetKit defaults to `sleep`. One of `"restart"`, `"sleep"`, `"destroy"`. | -| `rvt-skip-ready-wait` | `boolean` | No | Return as soon as the actor is resolved instead of waiting for it to be ready. | -| `rvt-token` | `string` | No | Token to authenticate with. Prefer the `x-rivet-token` header or inline path token when possible. | - - - -## Request Body - -Content type: `application/json` (optional). - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `args` | `any[]` | No | Positional arguments passed to the action, in order. | - -## Responses - -### 200 - -The action result. - -| Field | Type | Description | -| --- | --- | --- | -| `output` | `any` | Value returned by the action. `null` if the action returned `undefined`. | - -```json -{ - "output": 1 -} -``` - -### 401 - -The inspector token is missing or invalid. diff --git a/vendor/api/docs/content/inspector/connections.mdx b/vendor/api/docs/content/inspector/connections.mdx deleted file mode 100644 index 0e994292..00000000 --- a/vendor/api/docs/content/inspector/connections.mdx +++ /dev/null @@ -1,86 +0,0 @@ ---- -title: "List Connections" -description: "List the actor's active connections." ---- - -{/* Generated by scripts/docs/gen-api-reference.mjs from rivetkit-openapi/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} - - -The inspector API is subject to change without notice. Do not build production integrations on it. - - -```http -GET https://rivet.example.com/gateway/{actor}/inspector/connections -``` - -## Examples - - - -```bash cURL -curl "https://rivet.example.com/gateway/$ACTOR_ID/inspector/connections" \ - -H "Authorization: Bearer $INSPECTOR_TOKEN" -``` - - - - - -## Authentication - -Inspector endpoints do not accept namespace tokens. Send the actor's inspector token as a bearer token in the `Authorization` header. {/* TODO(code): document how to read an Actor's inspector token once an API returns it (ACT-6493). */} - -## Path Parameters - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `actor` | `string` | Yes | Actor ID, actor ID with an inline token (`{actor_id}@{token}`), or actor name combined with the `rvt-*` query parameters. | - -## Headers - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `Authorization` | `string` | No | Bearer token for inspector authentication. Required in production, optional in development. | - -## Actor Selector - -`{actor}` accepts an actor ID, an actor ID with an inline routing token (`{actor_id}@{token}`), or an actor name combined with the `rvt-*` query parameters below. See [Actor Routing](/docs/api/actor-routing) for the full rules. - - - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `rvt-namespace` | `string` | No | Namespace the actor lives in. Required when `{actor}` is an actor name. | -| `rvt-method` | `string` | No | How to resolve an actor name to an actor. `getOrCreate` requires `rvt-pool`. One of `"get"`, `"getOrCreate"`. | -| `rvt-key` | `string` | No | Actor key. Separate multi-part keys with commas. | -| `rvt-pool` | `string` | No | Pool to create the actor on when `rvt-method=getOrCreate`. RivetKit registers the `default` pool unless configured otherwise. | -| `rvt-runner` | `string` | No | Deprecated alias for `rvt-pool`. | -| `rvt-input` | `string` | No | Base64url-encoded CBOR input passed to `createState` and `onCreate` when `rvt-method=getOrCreate` creates the actor. | -| `rvt-region` | `string` | No | Preferred region when `rvt-method=getOrCreate` creates the actor. | -| `rvt-crash-policy` | `string` | No | Crash policy when `rvt-method=getOrCreate` creates the actor. RivetKit defaults to `sleep`. One of `"restart"`, `"sleep"`, `"destroy"`. | -| `rvt-skip-ready-wait` | `boolean` | No | Return as soon as the actor is resolved instead of waiting for it to be ready. | -| `rvt-token` | `string` | No | Token to authenticate with. Prefer the `x-rivet-token` header or inline path token when possible. | - - - -## Responses - -### 200 - -The active connections. - -| Field | Type | Description | -| --- | --- | --- | -| `connections` | `object[]` | | - -```json -{ - "connections": [ - {} - ] -} -``` - -### 401 - -The inspector token is missing or invalid. diff --git a/vendor/api/docs/content/inspector/database-execute.mdx b/vendor/api/docs/content/inspector/database-execute.mdx deleted file mode 100644 index b0697cf8..00000000 --- a/vendor/api/docs/content/inspector/database-execute.mdx +++ /dev/null @@ -1,84 +0,0 @@ ---- -title: "Execute SQL" -description: "Run a SQL statement against the actor's SQLite database." ---- - -{/* Generated by scripts/docs/gen-api-reference.mjs from rivetkit-openapi/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} - - -The inspector API is subject to change without notice. Do not build production integrations on it. - - -SQL executes directly against actor storage. Use bind parameters for values. - -```http -POST https://rivet.example.com/gateway/{actor}/inspector/database/execute -``` - -## Examples - - - -```bash cURL -curl -X POST "https://rivet.example.com/gateway/$ACTOR_ID/inspector/database/execute" \ - -H "Authorization: Bearer $INSPECTOR_TOKEN" \ - -H "Content-Type: application/json" \ - -d '{ - "sql": "SELECT * FROM users WHERE id = ?", - "args": [ - "user-123" - ] - }' -``` - - - - - -## Authentication - -Inspector endpoints do not accept namespace tokens. Send the actor's inspector token as a bearer token in the `Authorization` header. {/* TODO(code): document how to read an Actor's inspector token once an API returns it (ACT-6493). */} - -## Path Parameters - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `actor` | `string` | Yes | Actor ID, actor ID with an inline token (`{actor_id}@{token}`), or actor name combined with the `rvt-*` query parameters. | - -## Headers - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `Authorization` | `string` | No | Bearer token for inspector authentication. Required in production, optional in development. | - -## Request Body - -Content type: `application/json`. - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `sql` | `string` | Yes | SQL statement to run against the actor's SQLite database. | -| `args` | `any[]` | No | Positional arguments passed to the action, in order. | -| `properties` | `object` | No | Driver-specific execution options. | - -## Responses - -### 200 - -Rows returned by the statement. - -| Field | Type | Description | -| --- | --- | --- | -| `rows` | `object[]` | | - -```json -{ - "rows": [ - {} - ] -} -``` - -### 401 - -The inspector token is missing or invalid. diff --git a/vendor/api/docs/content/inspector/database-rows.mdx b/vendor/api/docs/content/inspector/database-rows.mdx deleted file mode 100644 index f966c2d3..00000000 --- a/vendor/api/docs/content/inspector/database-rows.mdx +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: "Query Database Rows" -description: "Read a page of rows from an actor database table or view." ---- - -{/* Generated by scripts/docs/gen-api-reference.mjs from rivetkit-openapi/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} - - -The inspector API is subject to change without notice. Do not build production integrations on it. - - -```http -GET https://rivet.example.com/gateway/{actor}/inspector/database/rows -``` - -## Examples - - - -```bash cURL -curl "https://rivet.example.com/gateway/$ACTOR_ID/inspector/database/rows?table=users&limit=100&offset=0" \ - -H "Authorization: Bearer $INSPECTOR_TOKEN" -``` - - - - - -## Authentication - -Inspector endpoints do not accept namespace tokens. Send the actor's inspector token as a bearer token in the `Authorization` header. {/* TODO(code): document how to read an Actor's inspector token once an API returns it (ACT-6493). */} - -## Path Parameters - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `actor` | `string` | Yes | Actor ID, actor ID with an inline token (`{actor_id}@{token}`), or actor name combined with the `rvt-*` query parameters. | - -## Query Parameters - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `table` | `string` | Yes | Table or view to read. | -| `limit` | `integer` | No | Maximum rows to return. | -| `offset` | `integer` | No | Rows to skip. | - -## Headers - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `Authorization` | `string` | No | Bearer token for inspector authentication. Required in production, optional in development. | - -## Responses - -### 200 - -The selected rows. - -| Field | Type | Description | -| --- | --- | --- | -| `rows` | `object[]` | | - -```json -{ - "rows": [ - {} - ] -} -``` - -### 401 - -The inspector token is missing or invalid. diff --git a/vendor/api/docs/content/inspector/database-schema.mdx b/vendor/api/docs/content/inspector/database-schema.mdx deleted file mode 100644 index beb6dada..00000000 --- a/vendor/api/docs/content/inspector/database-schema.mdx +++ /dev/null @@ -1,86 +0,0 @@ ---- -title: "Get Database Schema" -description: "List tables, views, and columns in the actor's SQLite database." ---- - -{/* Generated by scripts/docs/gen-api-reference.mjs from rivetkit-openapi/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} - - -The inspector API is subject to change without notice. Do not build production integrations on it. - - -```http -GET https://rivet.example.com/gateway/{actor}/inspector/database/schema -``` - -## Examples - - - -```bash cURL -curl "https://rivet.example.com/gateway/$ACTOR_ID/inspector/database/schema" \ - -H "Authorization: Bearer $INSPECTOR_TOKEN" -``` - - - - - -## Authentication - -Inspector endpoints do not accept namespace tokens. Send the actor's inspector token as a bearer token in the `Authorization` header. {/* TODO(code): document how to read an Actor's inspector token once an API returns it (ACT-6493). */} - -## Path Parameters - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `actor` | `string` | Yes | Actor ID, actor ID with an inline token (`{actor_id}@{token}`), or actor name combined with the `rvt-*` query parameters. | - -## Headers - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `Authorization` | `string` | No | Bearer token for inspector authentication. Required in production, optional in development. | - -## Responses - -### 200 - -The actor database schema. - -| Field | Type | Description | -| --- | --- | --- | -| `schema` | `object` | | -| `schema.tables` | `object[]` | | -| `schema.tables[].name` | `string` | | -| `schema.tables[].type` | `"table" \| "view"` | | -| `schema.tables[].columns` | `object[]` | | -| `schema.tables[].columns[].name` | `string` | | -| `schema.tables[].columns[].type` | `string` | | -| `schema.tables[].columns[].notnull` | `boolean` | | -| `schema.tables[].columns[].pk` | `boolean` | | - -```json -{ - "schema": { - "tables": [ - { - "name": "my-actor", - "type": "table", - "columns": [ - { - "name": "my-actor", - "type": "", - "notnull": false, - "pk": false - } - ] - } - ] - } -} -``` - -### 401 - -The inspector token is missing or invalid. diff --git a/vendor/api/docs/content/inspector/queue-delete.mdx b/vendor/api/docs/content/inspector/queue-delete.mdx deleted file mode 100644 index 154f8246..00000000 --- a/vendor/api/docs/content/inspector/queue-delete.mdx +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: "Clear Queue" -description: "Remove all pending messages from the actor's queue." ---- - -{/* Generated by scripts/docs/gen-api-reference.mjs from rivetkit-openapi/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} - - -The inspector API is subject to change without notice. Do not build production integrations on it. - - -```http -DELETE https://rivet.example.com/gateway/{actor}/inspector/queue -``` - -## Examples - - - -```bash cURL -curl -X DELETE "https://rivet.example.com/gateway/$ACTOR_ID/inspector/queue" \ - -H "Authorization: Bearer $INSPECTOR_TOKEN" -``` - - - - - -## Authentication - -Inspector endpoints do not accept namespace tokens. Send the actor's inspector token as a bearer token in the `Authorization` header. {/* TODO(code): document how to read an Actor's inspector token once an API returns it (ACT-6493). */} - -## Path Parameters - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `actor` | `string` | Yes | Actor ID, actor ID with an inline token (`{actor_id}@{token}`), or actor name combined with the `rvt-*` query parameters. | - -## Headers - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `Authorization` | `string` | No | Bearer token for inspector authentication. Required in production, optional in development. | - -## Responses - -### 200 - -The queue was cleared. - -```json -{} -``` - -### 401 - -The inspector token is missing or invalid. diff --git a/vendor/api/docs/content/inspector/queue-get.mdx b/vendor/api/docs/content/inspector/queue-get.mdx deleted file mode 100644 index 9939d3a6..00000000 --- a/vendor/api/docs/content/inspector/queue-get.mdx +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: "Get Queue" -description: "List pending queue messages and queue capacity details." ---- - -{/* Generated by scripts/docs/gen-api-reference.mjs from rivetkit-openapi/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} - - -The inspector API is subject to change without notice. Do not build production integrations on it. - - -```http -GET https://rivet.example.com/gateway/{actor}/inspector/queue -``` - -## Examples - - - -```bash cURL -curl "https://rivet.example.com/gateway/$ACTOR_ID/inspector/queue?limit=50" \ - -H "Authorization: Bearer $INSPECTOR_TOKEN" -``` - - - - - -## Authentication - -Inspector endpoints do not accept namespace tokens. Send the actor's inspector token as a bearer token in the `Authorization` header. {/* TODO(code): document how to read an Actor's inspector token once an API returns it (ACT-6493). */} - -## Path Parameters - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `actor` | `string` | Yes | Actor ID, actor ID with an inline token (`{actor_id}@{token}`), or actor name combined with the `rvt-*` query parameters. | - -## Query Parameters - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `limit` | `integer` | No | Maximum number of queue messages to return | - -## Headers - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `Authorization` | `string` | No | Bearer token for inspector authentication. Required in production, optional in development. | - -## Actor Selector - -`{actor}` accepts an actor ID, an actor ID with an inline routing token (`{actor_id}@{token}`), or an actor name combined with the `rvt-*` query parameters below. See [Actor Routing](/docs/api/actor-routing) for the full rules. - - - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `rvt-namespace` | `string` | No | Namespace the actor lives in. Required when `{actor}` is an actor name. | -| `rvt-method` | `string` | No | How to resolve an actor name to an actor. `getOrCreate` requires `rvt-pool`. One of `"get"`, `"getOrCreate"`. | -| `rvt-key` | `string` | No | Actor key. Separate multi-part keys with commas. | -| `rvt-pool` | `string` | No | Pool to create the actor on when `rvt-method=getOrCreate`. RivetKit registers the `default` pool unless configured otherwise. | -| `rvt-runner` | `string` | No | Deprecated alias for `rvt-pool`. | -| `rvt-input` | `string` | No | Base64url-encoded CBOR input passed to `createState` and `onCreate` when `rvt-method=getOrCreate` creates the actor. | -| `rvt-region` | `string` | No | Preferred region when `rvt-method=getOrCreate` creates the actor. | -| `rvt-crash-policy` | `string` | No | Crash policy when `rvt-method=getOrCreate` creates the actor. RivetKit defaults to `sleep`. One of `"restart"`, `"sleep"`, `"destroy"`. | -| `rvt-skip-ready-wait` | `boolean` | No | Return as soon as the actor is resolved instead of waiting for it to be ready. | -| `rvt-token` | `string` | No | Token to authenticate with. Prefer the `x-rivet-token` header or inline path token when possible. | - - - -## Responses - -### 200 - -Queue size, capacity, truncation status, and pending message metadata. - -| Field | Type | Description | -| --- | --- | --- | -| `size` | `integer` | | -| `maxSize` | `integer` | | -| `truncated` | `boolean` | | -| `messages` | `object[]` | | -| `messages[].id` | `string` | | -| `messages[].name` | `string` | | -| `messages[].createdAtMs` | `integer` | | - -```json -{ - "size": 0, - "maxSize": 0, - "truncated": false, - "messages": [ - { - "id": "", - "name": "my-actor", - "createdAtMs": 0 - } - ] -} -``` - -### 401 - -The inspector token is missing or invalid. diff --git a/vendor/api/docs/content/inspector/queue-post.mdx b/vendor/api/docs/content/inspector/queue-post.mdx deleted file mode 100644 index c7ecef96..00000000 --- a/vendor/api/docs/content/inspector/queue-post.mdx +++ /dev/null @@ -1,83 +0,0 @@ ---- -title: "Enqueue Message" -description: "Enqueue a message through the inspector." ---- - -{/* Generated by scripts/docs/gen-api-reference.mjs from rivetkit-openapi/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} - - -The inspector API is subject to change without notice. Do not build production integrations on it. - - -```http -POST https://rivet.example.com/gateway/{actor}/inspector/queue -``` - -## Examples - - - -```bash cURL -curl -X POST "https://rivet.example.com/gateway/$ACTOR_ID/inspector/queue" \ - -H "Authorization: Bearer $INSPECTOR_TOKEN" \ - -H "Content-Type: application/json" \ - -d '{ - "name": "increment", - "body": { - "amount": 1 - } - }' -``` - - - - - -## Authentication - -Inspector endpoints do not accept namespace tokens. Send the actor's inspector token as a bearer token in the `Authorization` header. {/* TODO(code): document how to read an Actor's inspector token once an API returns it (ACT-6493). */} - -## Path Parameters - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `actor` | `string` | Yes | Actor ID, actor ID with an inline token (`{actor_id}@{token}`), or actor name combined with the `rvt-*` query parameters. | - -## Headers - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `Authorization` | `string` | No | Bearer token for inspector authentication. Required in production, optional in development. | - -## Request Body - -Content type: `application/json`. - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `name` | `string` | Yes | Queue message name. | -| `body` | `any` | No | Message payload. Any JSON value. | - -## Responses - -### 200 - -Metadata for the enqueued message. - -| Field | Type | Description | -| --- | --- | --- | -| `id` | `string` | | -| `name` | `string` | | -| `createdAtMs` | `integer` | | - -```json -{ - "id": "", - "name": "my-actor", - "createdAtMs": 0 -} -``` - -### 401 - -The inspector token is missing or invalid. diff --git a/vendor/api/docs/content/inspector/rpcs.mdx b/vendor/api/docs/content/inspector/rpcs.mdx deleted file mode 100644 index 3807e06a..00000000 --- a/vendor/api/docs/content/inspector/rpcs.mdx +++ /dev/null @@ -1,84 +0,0 @@ ---- -title: "List Actions" -description: "List the actions exposed by the actor." ---- - -{/* Generated by scripts/docs/gen-api-reference.mjs from rivetkit-openapi/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} - - -The inspector API is subject to change without notice. Do not build production integrations on it. - - -```http -GET https://rivet.example.com/gateway/{actor}/inspector/rpcs -``` - -## Examples - - - -```bash cURL -curl "https://rivet.example.com/gateway/$ACTOR_ID/inspector/rpcs" \ - -H "Authorization: Bearer $INSPECTOR_TOKEN" -``` - - - - - -## Authentication - -Inspector endpoints do not accept namespace tokens. Send the actor's inspector token as a bearer token in the `Authorization` header. {/* TODO(code): document how to read an Actor's inspector token once an API returns it (ACT-6493). */} - -## Path Parameters - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `actor` | `string` | Yes | Actor ID, actor ID with an inline token (`{actor_id}@{token}`), or actor name combined with the `rvt-*` query parameters. | - -## Headers - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `Authorization` | `string` | No | Bearer token for inspector authentication. Required in production, optional in development. | - -## Actor Selector - -`{actor}` accepts an actor ID, an actor ID with an inline routing token (`{actor_id}@{token}`), or an actor name combined with the `rvt-*` query parameters below. See [Actor Routing](/docs/api/actor-routing) for the full rules. - - - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `rvt-namespace` | `string` | No | Namespace the actor lives in. Required when `{actor}` is an actor name. | -| `rvt-method` | `string` | No | How to resolve an actor name to an actor. `getOrCreate` requires `rvt-pool`. One of `"get"`, `"getOrCreate"`. | -| `rvt-key` | `string` | No | Actor key. Separate multi-part keys with commas. | -| `rvt-pool` | `string` | No | Pool to create the actor on when `rvt-method=getOrCreate`. RivetKit registers the `default` pool unless configured otherwise. | -| `rvt-runner` | `string` | No | Deprecated alias for `rvt-pool`. | -| `rvt-input` | `string` | No | Base64url-encoded CBOR input passed to `createState` and `onCreate` when `rvt-method=getOrCreate` creates the actor. | -| `rvt-region` | `string` | No | Preferred region when `rvt-method=getOrCreate` creates the actor. | -| `rvt-crash-policy` | `string` | No | Crash policy when `rvt-method=getOrCreate` creates the actor. RivetKit defaults to `sleep`. One of `"restart"`, `"sleep"`, `"destroy"`. | -| `rvt-skip-ready-wait` | `boolean` | No | Return as soon as the actor is resolved instead of waiting for it to be ready. | -| `rvt-token` | `string` | No | Token to authenticate with. Prefer the `x-rivet-token` header or inline path token when possible. | - - - -## Responses - -### 200 - -The actor's action definitions. - -| Field | Type | Description | -| --- | --- | --- | -| `rpcs` | `object` | | - -```json -{ - "rpcs": {} -} -``` - -### 401 - -The inspector token is missing or invalid. diff --git a/vendor/api/docs/content/inspector/state-get.mdx b/vendor/api/docs/content/inspector/state-get.mdx deleted file mode 100644 index c4605844..00000000 --- a/vendor/api/docs/content/inspector/state-get.mdx +++ /dev/null @@ -1,86 +0,0 @@ ---- -title: "Get State" -description: "Read the actor's current state." ---- - -{/* Generated by scripts/docs/gen-api-reference.mjs from rivetkit-openapi/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} - - -The inspector API is subject to change without notice. Do not build production integrations on it. - - -```http -GET https://rivet.example.com/gateway/{actor}/inspector/state -``` - -## Examples - - - -```bash cURL -curl "https://rivet.example.com/gateway/$ACTOR_ID/inspector/state" \ - -H "Authorization: Bearer $INSPECTOR_TOKEN" -``` - - - - - -## Authentication - -Inspector endpoints do not accept namespace tokens. Send the actor's inspector token as a bearer token in the `Authorization` header. {/* TODO(code): document how to read an Actor's inspector token once an API returns it (ACT-6493). */} - -## Path Parameters - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `actor` | `string` | Yes | Actor ID, actor ID with an inline token (`{actor_id}@{token}`), or actor name combined with the `rvt-*` query parameters. | - -## Headers - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `Authorization` | `string` | No | Bearer token for inspector authentication. Required in production, optional in development. | - -## Actor Selector - -`{actor}` accepts an actor ID, an actor ID with an inline routing token (`{actor_id}@{token}`), or an actor name combined with the `rvt-*` query parameters below. See [Actor Routing](/docs/api/actor-routing) for the full rules. - - - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `rvt-namespace` | `string` | No | Namespace the actor lives in. Required when `{actor}` is an actor name. | -| `rvt-method` | `string` | No | How to resolve an actor name to an actor. `getOrCreate` requires `rvt-pool`. One of `"get"`, `"getOrCreate"`. | -| `rvt-key` | `string` | No | Actor key. Separate multi-part keys with commas. | -| `rvt-pool` | `string` | No | Pool to create the actor on when `rvt-method=getOrCreate`. RivetKit registers the `default` pool unless configured otherwise. | -| `rvt-runner` | `string` | No | Deprecated alias for `rvt-pool`. | -| `rvt-input` | `string` | No | Base64url-encoded CBOR input passed to `createState` and `onCreate` when `rvt-method=getOrCreate` creates the actor. | -| `rvt-region` | `string` | No | Preferred region when `rvt-method=getOrCreate` creates the actor. | -| `rvt-crash-policy` | `string` | No | Crash policy when `rvt-method=getOrCreate` creates the actor. RivetKit defaults to `sleep`. One of `"restart"`, `"sleep"`, `"destroy"`. | -| `rvt-skip-ready-wait` | `boolean` | No | Return as soon as the actor is resolved instead of waiting for it to be ready. | -| `rvt-token` | `string` | No | Token to authenticate with. Prefer the `x-rivet-token` header or inline path token when possible. | - - - -## Responses - -### 200 - -The current actor state. - -| Field | Type | Description | -| --- | --- | --- | -| `state` | `any` | | - -```json -{ - "state": { - "count": 1 - } -} -``` - -### 401 - -The inspector token is missing or invalid. diff --git a/vendor/api/docs/content/inspector/state-patch.mdx b/vendor/api/docs/content/inspector/state-patch.mdx deleted file mode 100644 index 10156caa..00000000 --- a/vendor/api/docs/content/inspector/state-patch.mdx +++ /dev/null @@ -1,100 +0,0 @@ ---- -title: "Patch State" -description: "Replace the actor's current state." ---- - -{/* Generated by scripts/docs/gen-api-reference.mjs from rivetkit-openapi/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} - - -The inspector API is subject to change without notice. Do not build production integrations on it. - - -This writes state directly and bypasses actor actions. Use it only for inspection and recovery. - -```http -PATCH https://rivet.example.com/gateway/{actor}/inspector/state -``` - -## Examples - - - -```bash cURL -curl -X PATCH "https://rivet.example.com/gateway/$ACTOR_ID/inspector/state" \ - -H "Authorization: Bearer $INSPECTOR_TOKEN" \ - -H "Content-Type: application/json" \ - -d '{ - "state": { - "count": 2 - } - }' -``` - - - - - -## Authentication - -Inspector endpoints do not accept namespace tokens. Send the actor's inspector token as a bearer token in the `Authorization` header. {/* TODO(code): document how to read an Actor's inspector token once an API returns it (ACT-6493). */} - -## Path Parameters - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `actor` | `string` | Yes | Actor ID, actor ID with an inline token (`{actor_id}@{token}`), or actor name combined with the `rvt-*` query parameters. | - -## Headers - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `Authorization` | `string` | No | Bearer token for inspector authentication. Required in production, optional in development. | - -## Actor Selector - -`{actor}` accepts an actor ID, an actor ID with an inline routing token (`{actor_id}@{token}`), or an actor name combined with the `rvt-*` query parameters below. See [Actor Routing](/docs/api/actor-routing) for the full rules. - - - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `rvt-namespace` | `string` | No | Namespace the actor lives in. Required when `{actor}` is an actor name. | -| `rvt-method` | `string` | No | How to resolve an actor name to an actor. `getOrCreate` requires `rvt-pool`. One of `"get"`, `"getOrCreate"`. | -| `rvt-key` | `string` | No | Actor key. Separate multi-part keys with commas. | -| `rvt-pool` | `string` | No | Pool to create the actor on when `rvt-method=getOrCreate`. RivetKit registers the `default` pool unless configured otherwise. | -| `rvt-runner` | `string` | No | Deprecated alias for `rvt-pool`. | -| `rvt-input` | `string` | No | Base64url-encoded CBOR input passed to `createState` and `onCreate` when `rvt-method=getOrCreate` creates the actor. | -| `rvt-region` | `string` | No | Preferred region when `rvt-method=getOrCreate` creates the actor. | -| `rvt-crash-policy` | `string` | No | Crash policy when `rvt-method=getOrCreate` creates the actor. RivetKit defaults to `sleep`. One of `"restart"`, `"sleep"`, `"destroy"`. | -| `rvt-skip-ready-wait` | `boolean` | No | Return as soon as the actor is resolved instead of waiting for it to be ready. | -| `rvt-token` | `string` | No | Token to authenticate with. Prefer the `x-rivet-token` header or inline path token when possible. | - - - -## Request Body - -Content type: `application/json` (optional). - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `state` | `any` | Yes | | - -## Responses - -### 200 - -The state was saved. - -| Field | Type | Description | -| --- | --- | --- | -| `ok` | `boolean` | | - -```json -{ - "ok": true -} -``` - -### 401 - -The inspector token is missing or invalid. diff --git a/vendor/api/docs/content/inspector/summary.mdx b/vendor/api/docs/content/inspector/summary.mdx deleted file mode 100644 index e280b745..00000000 --- a/vendor/api/docs/content/inspector/summary.mdx +++ /dev/null @@ -1,100 +0,0 @@ ---- -title: "Get Summary" -description: "Get an overview of an actor's state, connections, actions, queue, database, and workflow." ---- - -{/* Generated by scripts/docs/gen-api-reference.mjs from rivetkit-openapi/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} - - -The inspector API is subject to change without notice. Do not build production integrations on it. - - -```http -GET https://rivet.example.com/gateway/{actor}/inspector/summary -``` - -## Examples - - - -```bash cURL -curl "https://rivet.example.com/gateway/$ACTOR_ID/inspector/summary" \ - -H "Authorization: Bearer $INSPECTOR_TOKEN" -``` - - - - - -## Authentication - -Inspector endpoints do not accept namespace tokens. Send the actor's inspector token as a bearer token in the `Authorization` header. {/* TODO(code): document how to read an Actor's inspector token once an API returns it (ACT-6493). */} - -## Path Parameters - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `actor` | `string` | Yes | Actor ID, actor ID with an inline token (`{actor_id}@{token}`), or actor name combined with the `rvt-*` query parameters. | - -## Headers - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `Authorization` | `string` | No | Bearer token for inspector authentication. Required in production, optional in development. | - -## Actor Selector - -`{actor}` accepts an actor ID, an actor ID with an inline routing token (`{actor_id}@{token}`), or an actor name combined with the `rvt-*` query parameters below. See [Actor Routing](/docs/api/actor-routing) for the full rules. - - - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `rvt-namespace` | `string` | No | Namespace the actor lives in. Required when `{actor}` is an actor name. | -| `rvt-method` | `string` | No | How to resolve an actor name to an actor. `getOrCreate` requires `rvt-pool`. One of `"get"`, `"getOrCreate"`. | -| `rvt-key` | `string` | No | Actor key. Separate multi-part keys with commas. | -| `rvt-pool` | `string` | No | Pool to create the actor on when `rvt-method=getOrCreate`. RivetKit registers the `default` pool unless configured otherwise. | -| `rvt-runner` | `string` | No | Deprecated alias for `rvt-pool`. | -| `rvt-input` | `string` | No | Base64url-encoded CBOR input passed to `createState` and `onCreate` when `rvt-method=getOrCreate` creates the actor. | -| `rvt-region` | `string` | No | Preferred region when `rvt-method=getOrCreate` creates the actor. | -| `rvt-crash-policy` | `string` | No | Crash policy when `rvt-method=getOrCreate` creates the actor. RivetKit defaults to `sleep`. One of `"restart"`, `"sleep"`, `"destroy"`. | -| `rvt-skip-ready-wait` | `boolean` | No | Return as soon as the actor is resolved instead of waiting for it to be ready. | -| `rvt-token` | `string` | No | Token to authenticate with. Prefer the `x-rivet-token` header or inline path token when possible. | - - - -## Responses - -### 200 - -The actor inspector summary. - -| Field | Type | Description | -| --- | --- | --- | -| `state` | `any` | | -| `connections` | `object[]` | | -| `rpcs` | `object` | | -| `queueSize` | `integer` | | -| `isStateEnabled` | `boolean` | | -| `isDatabaseEnabled` | `boolean` | | -| `isWorkflowEnabled` | `boolean` | | -| `workflowHistory` | `any` | | - -```json -{ - "state": "", - "connections": [ - {} - ], - "rpcs": {}, - "queueSize": 0, - "isStateEnabled": false, - "isDatabaseEnabled": false, - "isWorkflowEnabled": false, - "workflowHistory": "" -} -``` - -### 401 - -The inspector token is missing or invalid. diff --git a/vendor/api/docs/content/inspector/traces.mdx b/vendor/api/docs/content/inspector/traces.mdx deleted file mode 100644 index 97b100c4..00000000 --- a/vendor/api/docs/content/inspector/traces.mdx +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: "Get Traces" -description: "Get actor trace spans in OTLP JSON format." ---- - -{/* Generated by scripts/docs/gen-api-reference.mjs from rivetkit-openapi/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} - - -The inspector API is subject to change without notice. Do not build production integrations on it. - - -Trace collection is not implemented yet, so this route currently returns an empty result. - -```http -GET https://rivet.example.com/gateway/{actor}/inspector/traces -``` - -## Examples - - - -```bash cURL -curl "https://rivet.example.com/gateway/$ACTOR_ID/inspector/traces?startMs=0&limit=100" \ - -H "Authorization: Bearer $INSPECTOR_TOKEN" -``` - - - - - -## Authentication - -Inspector endpoints do not accept namespace tokens. Send the actor's inspector token as a bearer token in the `Authorization` header. {/* TODO(code): document how to read an Actor's inspector token once an API returns it (ACT-6493). */} - -## Path Parameters - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `actor` | `string` | Yes | Actor ID, actor ID with an inline token (`{actor_id}@{token}`), or actor name combined with the `rvt-*` query parameters. | - -## Query Parameters - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `startMs` | `integer` | No | Start of time range in epoch milliseconds | -| `endMs` | `integer` | No | End of time range in epoch milliseconds. Defaults to now. | -| `limit` | `integer` | No | Maximum number of spans to return | - -## Headers - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `Authorization` | `string` | No | Bearer token for inspector authentication. Required in production, optional in development. | - -## Actor Selector - -`{actor}` accepts an actor ID, an actor ID with an inline routing token (`{actor_id}@{token}`), or an actor name combined with the `rvt-*` query parameters below. See [Actor Routing](/docs/api/actor-routing) for the full rules. - - - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `rvt-namespace` | `string` | No | Namespace the actor lives in. Required when `{actor}` is an actor name. | -| `rvt-method` | `string` | No | How to resolve an actor name to an actor. `getOrCreate` requires `rvt-pool`. One of `"get"`, `"getOrCreate"`. | -| `rvt-key` | `string` | No | Actor key. Separate multi-part keys with commas. | -| `rvt-pool` | `string` | No | Pool to create the actor on when `rvt-method=getOrCreate`. RivetKit registers the `default` pool unless configured otherwise. | -| `rvt-runner` | `string` | No | Deprecated alias for `rvt-pool`. | -| `rvt-input` | `string` | No | Base64url-encoded CBOR input passed to `createState` and `onCreate` when `rvt-method=getOrCreate` creates the actor. | -| `rvt-region` | `string` | No | Preferred region when `rvt-method=getOrCreate` creates the actor. | -| `rvt-crash-policy` | `string` | No | Crash policy when `rvt-method=getOrCreate` creates the actor. RivetKit defaults to `sleep`. One of `"restart"`, `"sleep"`, `"destroy"`. | -| `rvt-skip-ready-wait` | `boolean` | No | Return as soon as the actor is resolved instead of waiting for it to be ready. | -| `rvt-token` | `string` | No | Token to authenticate with. Prefer the `x-rivet-token` header or inline path token when possible. | - - - -## Responses - -### 200 - -Trace data and whether the requested range was clamped. - -| Field | Type | Description | -| --- | --- | --- | -| `otlp` | `object` | | -| `clamped` | `boolean` | | - -```json -{ - "otlp": {}, - "clamped": false -} -``` - -### 401 - -The inspector token is missing or invalid. diff --git a/vendor/api/docs/content/inspector/workflow-history.mdx b/vendor/api/docs/content/inspector/workflow-history.mdx deleted file mode 100644 index 16cef287..00000000 --- a/vendor/api/docs/content/inspector/workflow-history.mdx +++ /dev/null @@ -1,86 +0,0 @@ ---- -title: "Get Workflow History" -description: "Read workflow history and whether workflows are enabled for the actor." ---- - -{/* Generated by scripts/docs/gen-api-reference.mjs from rivetkit-openapi/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} - - -The inspector API is subject to change without notice. Do not build production integrations on it. - - -```http -GET https://rivet.example.com/gateway/{actor}/inspector/workflow-history -``` - -## Examples - - - -```bash cURL -curl "https://rivet.example.com/gateway/$ACTOR_ID/inspector/workflow-history" \ - -H "Authorization: Bearer $INSPECTOR_TOKEN" -``` - - - - - -## Authentication - -Inspector endpoints do not accept namespace tokens. Send the actor's inspector token as a bearer token in the `Authorization` header. {/* TODO(code): document how to read an Actor's inspector token once an API returns it (ACT-6493). */} - -## Path Parameters - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `actor` | `string` | Yes | Actor ID, actor ID with an inline token (`{actor_id}@{token}`), or actor name combined with the `rvt-*` query parameters. | - -## Headers - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `Authorization` | `string` | No | Bearer token for inspector authentication. Required in production, optional in development. | - -## Actor Selector - -`{actor}` accepts an actor ID, an actor ID with an inline routing token (`{actor_id}@{token}`), or an actor name combined with the `rvt-*` query parameters below. See [Actor Routing](/docs/api/actor-routing) for the full rules. - - - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `rvt-namespace` | `string` | No | Namespace the actor lives in. Required when `{actor}` is an actor name. | -| `rvt-method` | `string` | No | How to resolve an actor name to an actor. `getOrCreate` requires `rvt-pool`. One of `"get"`, `"getOrCreate"`. | -| `rvt-key` | `string` | No | Actor key. Separate multi-part keys with commas. | -| `rvt-pool` | `string` | No | Pool to create the actor on when `rvt-method=getOrCreate`. RivetKit registers the `default` pool unless configured otherwise. | -| `rvt-runner` | `string` | No | Deprecated alias for `rvt-pool`. | -| `rvt-input` | `string` | No | Base64url-encoded CBOR input passed to `createState` and `onCreate` when `rvt-method=getOrCreate` creates the actor. | -| `rvt-region` | `string` | No | Preferred region when `rvt-method=getOrCreate` creates the actor. | -| `rvt-crash-policy` | `string` | No | Crash policy when `rvt-method=getOrCreate` creates the actor. RivetKit defaults to `sleep`. One of `"restart"`, `"sleep"`, `"destroy"`. | -| `rvt-skip-ready-wait` | `boolean` | No | Return as soon as the actor is resolved instead of waiting for it to be ready. | -| `rvt-token` | `string` | No | Token to authenticate with. Prefer the `x-rivet-token` header or inline path token when possible. | - - - -## Responses - -### 200 - -Workflow history and availability. - -| Field | Type | Description | -| --- | --- | --- | -| `history` | `any` | | -| `isWorkflowEnabled` | `boolean` | | - -```json -{ - "history": "", - "isWorkflowEnabled": false -} -``` - -### 401 - -The inspector token is missing or invalid. diff --git a/vendor/api/docs/content/inspector/workflow-replay.mdx b/vendor/api/docs/content/inspector/workflow-replay.mdx deleted file mode 100644 index a879d913..00000000 --- a/vendor/api/docs/content/inspector/workflow-replay.mdx +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: "Replay Workflow" -description: "Schedule a workflow replay from an optional history entry." ---- - -{/* Generated by scripts/docs/gen-api-reference.mjs from rivetkit-openapi/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} - - -The inspector API is subject to change without notice. Do not build production integrations on it. - - -```http -POST https://rivet.example.com/gateway/{actor}/inspector/workflow/replay -``` - -## Examples - - - -```bash cURL -curl -X POST "https://rivet.example.com/gateway/$ACTOR_ID/inspector/workflow/replay" \ - -H "Authorization: Bearer $INSPECTOR_TOKEN" \ - -H "Content-Type: application/json" \ - -d '{ - "entryId": "entry-123" - }' -``` - - - - - -## Authentication - -Inspector endpoints do not accept namespace tokens. Send the actor's inspector token as a bearer token in the `Authorization` header. {/* TODO(code): document how to read an Actor's inspector token once an API returns it (ACT-6493). */} - -## Path Parameters - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `actor` | `string` | Yes | Actor ID, actor ID with an inline token (`{actor_id}@{token}`), or actor name combined with the `rvt-*` query parameters. | - -## Headers - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `Authorization` | `string` | No | Bearer token for inspector authentication. Required in production, optional in development. | - -## Actor Selector - -`{actor}` accepts an actor ID, an actor ID with an inline routing token (`{actor_id}@{token}`), or an actor name combined with the `rvt-*` query parameters below. See [Actor Routing](/docs/api/actor-routing) for the full rules. - - - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `rvt-namespace` | `string` | No | Namespace the actor lives in. Required when `{actor}` is an actor name. | -| `rvt-method` | `string` | No | How to resolve an actor name to an actor. `getOrCreate` requires `rvt-pool`. One of `"get"`, `"getOrCreate"`. | -| `rvt-key` | `string` | No | Actor key. Separate multi-part keys with commas. | -| `rvt-pool` | `string` | No | Pool to create the actor on when `rvt-method=getOrCreate`. RivetKit registers the `default` pool unless configured otherwise. | -| `rvt-runner` | `string` | No | Deprecated alias for `rvt-pool`. | -| `rvt-input` | `string` | No | Base64url-encoded CBOR input passed to `createState` and `onCreate` when `rvt-method=getOrCreate` creates the actor. | -| `rvt-region` | `string` | No | Preferred region when `rvt-method=getOrCreate` creates the actor. | -| `rvt-crash-policy` | `string` | No | Crash policy when `rvt-method=getOrCreate` creates the actor. RivetKit defaults to `sleep`. One of `"restart"`, `"sleep"`, `"destroy"`. | -| `rvt-skip-ready-wait` | `boolean` | No | Return as soon as the actor is resolved instead of waiting for it to be ready. | -| `rvt-token` | `string` | No | Token to authenticate with. Prefer the `x-rivet-token` header or inline path token when possible. | - - - -## Request Body - -Content type: `application/json` (optional). - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `entryId` | `string` | No | | - -## Responses - -### 200 - -Workflow history after scheduling the replay. - -| Field | Type | Description | -| --- | --- | --- | -| `history` | `any` | | -| `isWorkflowEnabled` | `boolean` | | - -```json -{ - "history": "", - "isWorkflowEnabled": false -} -``` - -### 401 - -The inspector token is missing or invalid. diff --git a/vendor/api/docs/content/namespaces/create.mdx b/vendor/api/docs/content/namespaces/create.mdx index 79fb7779..7ee5d607 100644 --- a/vendor/api/docs/content/namespaces/create.mdx +++ b/vendor/api/docs/content/namespaces/create.mdx @@ -1,6 +1,6 @@ --- title: "Create Namespace" -description: "Create a namespace with a unique name." +description: "Create a namespace with a unique name and a display name." --- {/* Generated by scripts/docs/gen-api-reference.mjs from engine/artifacts/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} @@ -18,7 +18,8 @@ curl -X POST "https://rivet.example.com/namespaces" \ -H "Authorization: Bearer $RIVET_TOKEN" \ -H "Content-Type: application/json" \ -d '{ - "name": "my-app" + "name": "my-app", + "display_name": "My App" }' ``` @@ -28,7 +29,7 @@ curl -X POST "https://rivet.example.com/namespaces" \ ## Authentication -Requires the admin token, sent as a bearer token in the `Authorization` header. Namespace tokens are rejected. See [Authentication](/docs/api/authentication). +Send your namespace token as a bearer token in the `Authorization` header. Every control plane request also requires the `namespace` query parameter. See [Authentication](/docs/api/authentication). ## Request Body @@ -36,7 +37,7 @@ Content type: `application/json`. | Field | Type | Required | Description | | --- | --- | --- | --- | -| `name` | `string` | Yes | Unique name of the namespace. A DNS label of 1 to 63 lowercase letters, digits and hyphens. | +| `name` | `string` | Yes | Unique name used to identify the namespace. | ## Responses @@ -46,7 +47,7 @@ The newly created namespace. | Field | Type | Description | | --- | --- | --- | -| `namespace` | `object` | The created namespace. | +| `namespace` | `object` | Name of the namespace to operate in. | | `namespace.name` | `string` | Namespace name. | | `namespace.create_ts` | `integer` | When the namespace was created, in Unix milliseconds. | diff --git a/vendor/api/docs/content/namespaces/list.mdx b/vendor/api/docs/content/namespaces/list.mdx index 5593a1bb..0ae1d39d 100644 --- a/vendor/api/docs/content/namespaces/list.mdx +++ b/vendor/api/docs/content/namespaces/list.mdx @@ -1,11 +1,11 @@ --- title: "List Namespaces" -description: "List namespaces in name order, or look up one namespace by name. Results are paginated." +description: "List namespaces, optionally filtered by name or ID. Results are paginated." --- {/* Generated by scripts/docs/gen-api-reference.mjs from engine/artifacts/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} -`name` returns zero or one namespace and ignores `limit` and `cursor`. Any other query parameter, including `namespace`, is rejected. +Use `namespace_id` for multiple IDs. `namespace_ids` is deprecated. ```http GET https://rivet.example.com/namespaces @@ -26,15 +26,15 @@ curl "https://rivet.example.com/namespaces" \ ## Authentication -Requires the admin token, sent as a bearer token in the `Authorization` header. Namespace tokens are rejected. See [Authentication](/docs/api/authentication). +Send your namespace token as a bearer token in the `Authorization` header. Every control plane request also requires the `namespace` query parameter. See [Authentication](/docs/api/authentication). ## Query Parameters | Name | Type | Required | Description | | --- | --- | --- | --- | -| `name` | `string` | No | Only return the namespace with this name. | +| `name` | `string` | No | Only return namespaces with this name. | | `cursor` | `string` | No | Pagination cursor. Pass the `pagination.cursor` value from the previous response to fetch the next page. | -| `limit` | `integer` | No | Maximum number of results to return, from 1 to 100. Defaults to 100. | +| `limit` | `integer` | No | Maximum number of results to return. | ## Responses diff --git a/vendor/api/docs/content/pools/delete.mdx b/vendor/api/docs/content/pools/delete.mdx index a50f177d..dabd4039 100644 --- a/vendor/api/docs/content/pools/delete.mdx +++ b/vendor/api/docs/content/pools/delete.mdx @@ -1,11 +1,11 @@ --- -title: "Delete Node Pool" -description: "Delete a node pool's configuration." +title: "Delete Pool" +description: "Delete a node pool." --- {/* Generated by scripts/docs/gen-api-reference.mjs from engine/artifacts/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} -Fails with `pool.nodes_connected` while any node of the pool is connected. A namespace token needs a grant on `pool` with `delete`. +Fails with `pool.nodes_connected` while any node of the pool is connected. ```http DELETE https://rivet.example.com/pools/{pool} @@ -16,15 +16,17 @@ DELETE https://rivet.example.com/pools/{pool} ```bash cURL -curl -X DELETE "https://rivet.example.com/pools/default?namespace=$RIVET_NAMESPACE" \ +curl -X DELETE "https://rivet.example.com/pools/$RIVET_POOL?namespace=$RIVET_NAMESPACE" \ -H "Authorization: Bearer $RIVET_TOKEN" ``` + + ## Authentication -Send the admin token, or a namespace token from [Create Token](/docs/api/tokens/create) whose grants cover the request, as a bearer token in the `Authorization` header. The `x-rivet-token` header is also accepted. Routes with a `namespace` query parameter use the `default` namespace when it is omitted. See [Authentication](/docs/api/authentication). +Send your namespace token as a bearer token in the `Authorization` header. Every control plane request also requires the `namespace` query parameter. See [Authentication](/docs/api/authentication). ## Path Parameters @@ -36,13 +38,13 @@ Send the admin token, or a namespace token from [Create Token](/docs/api/tokens/ | Name | Type | Required | Description | | --- | --- | --- | --- | -| `namespace` | `string` | No | Name of the namespace to operate in. Defaults to `default`. | +| `namespace` | `string` | No | Name of the namespace to operate in. | ## Responses ### 200 -The node pool was deleted. The response body is an empty object. +The node pool was deleted. ```json {} diff --git a/vendor/api/docs/content/pools/get.mdx b/vendor/api/docs/content/pools/get.mdx index 84b6b555..522f3509 100644 --- a/vendor/api/docs/content/pools/get.mdx +++ b/vendor/api/docs/content/pools/get.mdx @@ -1,12 +1,10 @@ --- -title: "Get Node Pool" +title: "Get Pool" description: "Get a node pool's configuration." --- {/* Generated by scripts/docs/gen-api-reference.mjs from engine/artifacts/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} -A namespace token needs a grant on `pool` with `read`. - ```http GET https://rivet.example.com/pools/{pool} ``` @@ -16,15 +14,17 @@ GET https://rivet.example.com/pools/{pool} ```bash cURL -curl "https://rivet.example.com/pools/default?namespace=$RIVET_NAMESPACE" \ +curl "https://rivet.example.com/pools/$RIVET_POOL?namespace=$RIVET_NAMESPACE" \ -H "Authorization: Bearer $RIVET_TOKEN" ``` + + ## Authentication -Send the admin token, or a namespace token from [Create Token](/docs/api/tokens/create) whose grants cover the request, as a bearer token in the `Authorization` header. The `x-rivet-token` header is also accepted. Routes with a `namespace` query parameter use the `default` namespace when it is omitted. See [Authentication](/docs/api/authentication). +Send your namespace token as a bearer token in the `Authorization` header. Every control plane request also requires the `namespace` query parameter. See [Authentication](/docs/api/authentication). ## Path Parameters @@ -36,7 +36,7 @@ Send the admin token, or a namespace token from [Create Token](/docs/api/tokens/ | Name | Type | Required | Description | | --- | --- | --- | --- | -| `namespace` | `string` | No | Name of the namespace to operate in. Defaults to `default`. | +| `namespace` | `string` | No | Name of the namespace to operate in. | ## Responses diff --git a/vendor/api/docs/content/pools/list-nodes.mdx b/vendor/api/docs/content/pools/list-nodes.mdx index 547810a8..11cdcfb2 100644 --- a/vendor/api/docs/content/pools/list-nodes.mdx +++ b/vendor/api/docs/content/pools/list-nodes.mdx @@ -1,12 +1,10 @@ --- -title: "List Nodes" +title: "List Pool Nodes" description: "List the live nodes of a node pool in node key order. Results are paginated." --- {/* Generated by scripts/docs/gen-api-reference.mjs from engine/artifacts/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} -A node is listed while its heartbeat is recent enough for it to receive actors. A page can hold fewer than `limit` nodes while `pagination.cursor` is still set. A namespace token needs a grant on `node` with `list`. - ```http GET https://rivet.example.com/pools/{pool}/nodes ``` @@ -16,15 +14,17 @@ GET https://rivet.example.com/pools/{pool}/nodes ```bash cURL -curl "https://rivet.example.com/pools/default/nodes?namespace=$RIVET_NAMESPACE" \ +curl "https://rivet.example.com/pools/$RIVET_POOL/nodes?namespace=$RIVET_NAMESPACE" \ -H "Authorization: Bearer $RIVET_TOKEN" ``` + + ## Authentication -Send the admin token, or a namespace token from [Create Token](/docs/api/tokens/create) whose grants cover the request, as a bearer token in the `Authorization` header. The `x-rivet-token` header is also accepted. Routes with a `namespace` query parameter use the `default` namespace when it is omitted. See [Authentication](/docs/api/authentication). +Send your namespace token as a bearer token in the `Authorization` header. Every control plane request also requires the `namespace` query parameter. See [Authentication](/docs/api/authentication). ## Path Parameters @@ -36,15 +36,15 @@ Send the admin token, or a namespace token from [Create Token](/docs/api/tokens/ | Name | Type | Required | Description | | --- | --- | --- | --- | -| `namespace` | `string` | No | Name of the namespace to operate in. Defaults to `default`. | -| `limit` | `integer` | No | Maximum number of results to return, from 1 to 100. Defaults to 100. | +| `namespace` | `string` | No | Name of the namespace to operate in. | +| `limit` | `integer` | No | Maximum number of results to return. | | `cursor` | `string` | No | Pagination cursor. Pass the `pagination.cursor` value from the previous response to fetch the next page. | ## Responses ### 200 -A page of live nodes and a cursor for the next page. +A page of live nodes. | Field | Type | Description | | --- | --- | --- | @@ -53,6 +53,7 @@ A page of live nodes and a cursor for the next page. | `nodes[].pool` | `string` | Name of the node pool. | | `nodes[].namespace` | `string` | Name of the namespace. | | `nodes[].datacenter` | `string` | Datacenter name. | +| `nodes[].version` | `integer` | Version the node announced when it connected. New actors are placed only on nodes at the newest version with a connected node in the pool. | | `nodes[].create_ts` | `integer` | When the node connected, in Unix milliseconds. | | `nodes[].last_ping_ts` | `integer` | When the node last sent a heartbeat, in Unix milliseconds. | | `nodes[].connected` | `boolean` | Whether the node is connected. | @@ -68,6 +69,7 @@ A page of live nodes and a cursor for the next page. "pool": "default", "namespace": "my-namespace", "datacenter": "default", + "version": 3, "create_ts": 1700000000000, "last_ping_ts": 1700000000000, "connected": false, diff --git a/vendor/api/docs/content/pools/list.mdx b/vendor/api/docs/content/pools/list.mdx index 40e8dd11..7c975b92 100644 --- a/vendor/api/docs/content/pools/list.mdx +++ b/vendor/api/docs/content/pools/list.mdx @@ -1,12 +1,10 @@ --- -title: "List Node Pools" +title: "List Pools" description: "List the node pools configured in a namespace, ordered by name. Results are paginated." --- {/* Generated by scripts/docs/gen-api-reference.mjs from engine/artifacts/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} -A pool is listed once it is configured, whether or not any node is connected. A namespace token needs a grant on `pool` with `list`. - ```http GET https://rivet.example.com/pools ``` @@ -20,25 +18,27 @@ curl "https://rivet.example.com/pools?namespace=$RIVET_NAMESPACE" \ -H "Authorization: Bearer $RIVET_TOKEN" ``` + + ## Authentication -Send the admin token, or a namespace token from [Create Token](/docs/api/tokens/create) whose grants cover the request, as a bearer token in the `Authorization` header. The `x-rivet-token` header is also accepted. Routes with a `namespace` query parameter use the `default` namespace when it is omitted. See [Authentication](/docs/api/authentication). +Send your namespace token as a bearer token in the `Authorization` header. Every control plane request also requires the `namespace` query parameter. See [Authentication](/docs/api/authentication). ## Query Parameters | Name | Type | Required | Description | | --- | --- | --- | --- | -| `namespace` | `string` | No | Name of the namespace to operate in. Defaults to `default`. | -| `limit` | `integer` | No | Maximum number of results to return, from 1 to 100. Defaults to 100. | +| `namespace` | `string` | No | Name of the namespace to operate in. | +| `limit` | `integer` | No | Maximum number of results to return. | | `cursor` | `string` | No | Pagination cursor. Pass the `pagination.cursor` value from the previous response to fetch the next page. | ## Responses ### 200 -A page of node pools and a cursor for the next page. +A page of node pools. | Field | Type | Description | | --- | --- | --- | diff --git a/vendor/api/docs/content/pools/upsert.mdx b/vendor/api/docs/content/pools/upsert.mdx index f2c35909..4945e4ac 100644 --- a/vendor/api/docs/content/pools/upsert.mdx +++ b/vendor/api/docs/content/pools/upsert.mdx @@ -1,11 +1,11 @@ --- -title: "Upsert Node Pool" +title: "Upsert Pool" description: "Create or replace a node pool's configuration." --- {/* Generated by scripts/docs/gen-api-reference.mjs from engine/artifacts/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} -Every field is optional and omitted fields take their defaults, so a request replaces the whole configuration. Unknown fields are rejected. Serverless pools are not supported. Nodes pick up the new configuration on their next connection. A namespace token needs a grant on `pool` with `update`. +Omitted fields take their defaults. Unknown fields are rejected. ```http PUT https://rivet.example.com/pools/{pool} @@ -16,22 +16,21 @@ PUT https://rivet.example.com/pools/{pool} ```bash cURL -curl -X PUT "https://rivet.example.com/pools/default?namespace=$RIVET_NAMESPACE" \ +curl -X PUT "https://rivet.example.com/pools/$RIVET_POOL?namespace=$RIVET_NAMESPACE" \ -H "Authorization: Bearer $RIVET_TOKEN" \ -H "Content-Type: application/json" \ -d '{ - "drain_on_version_upgrade": true, - "actor_eviction_delay": 0, - "actor_eviction_period": 0, - "actor_eviction_rate": 1 + "drain_on_version_upgrade": true }' ``` + + ## Authentication -Send the admin token, or a namespace token from [Create Token](/docs/api/tokens/create) whose grants cover the request, as a bearer token in the `Authorization` header. The `x-rivet-token` header is also accepted. Routes with a `namespace` query parameter use the `default` namespace when it is omitted. See [Authentication](/docs/api/authentication). +Send your namespace token as a bearer token in the `Authorization` header. Every control plane request also requires the `namespace` query parameter. See [Authentication](/docs/api/authentication). ## Path Parameters @@ -43,7 +42,7 @@ Send the admin token, or a namespace token from [Create Token](/docs/api/tokens/ | Name | Type | Required | Description | | --- | --- | --- | --- | -| `namespace` | `string` | No | Name of the namespace to operate in. Defaults to `default`. | +| `namespace` | `string` | No | Name of the namespace to operate in. | ## Request Body diff --git a/vendor/api/docs/content/tokens/create.mdx b/vendor/api/docs/content/tokens/create.mdx index efc7a752..c7fd2e91 100644 --- a/vendor/api/docs/content/tokens/create.mdx +++ b/vendor/api/docs/content/tokens/create.mdx @@ -5,7 +5,7 @@ description: "Issue a scoped token. Use this to mint short-lived tokens that gra {/* Generated by scripts/docs/gen-api-reference.mjs from engine/artifacts/openapi.json and docs/api/endpoints.json. Do not edit by hand. */} -Each grant names a resource type, a target (`"any"` or a specific `{ "id": ... }`), and the operations it allows. A token carries 1 to 32 grants with 1 to 5 operations each. The RivetKit client wraps this as `handle.issueToken()`. +Each grant names a resource type, a target (`"any"` or a specific `{ "id": ... }`), and the operations it allows. The RivetKit client wraps this as `handle.issueToken()`. ```http POST https://rivet.example.com/auth/tokens @@ -27,7 +27,7 @@ curl -X POST "https://rivet.example.com/auth/tokens" \ { "resource": "actor_gateway", "target": { - "id": "d97pbq1nyqxw1w5qdwz0iirbqiblh2" + "id": "00000000-0000-0000-0000-000000000000" }, "operations": [ "read" @@ -43,7 +43,7 @@ curl -X POST "https://rivet.example.com/auth/tokens" \ ## Authentication -Requires the admin token, sent as a bearer token in the `Authorization` header. Namespace tokens are rejected. See [Authentication](/docs/api/authentication). +Send your namespace token as a bearer token in the `Authorization` header. Every control plane request also requires the `namespace` query parameter. See [Authentication](/docs/api/authentication). ## Request Body @@ -51,9 +51,9 @@ Content type: `application/json`. | Field | Type | Required | Description | | --- | --- | --- | --- | -| `namespace` | `string` | Yes | Namespace the token is valid in. It must exist. | -| `duration` | `integer \| null` | No | Lifetime in seconds, from 1 to the deployment's maximum. Omit for the default lifetime. | -| `subject` | `string \| null` | No | Free-form subject to attach to the token, such as a user ID. At most 256 UTF-8 bytes. | +| `namespace` | `string` | Yes | Namespace the token is valid in. | +| `duration` | `integer \| null` | No | Lifetime in seconds. Omit for the default lifetime. | +| `subject` | `string \| null` | No | Free-form subject to attach to the token, such as a user ID. | | `grants` | `object[]` | Yes | Permissions the token carries. | | `grants[].resource` | `"namespace" \| "actor" \| "node" \| "pool" \| "datacenter" \| "actor_gateway" \| "actor_kv"` | Yes | Resource type the grant applies to. | | `grants[].target` | `"any" \| object` | Yes | `"any"` for every resource of this type, or `{ "id": "..." }` for one resource. | @@ -81,7 +81,7 @@ The issued token. The response carries `Cache-Control: no-store`. ### 400 -`validation.invalid_input`: the subject exceeds 256 UTF-8 bytes, the duration is outside the allowed range, or the grant set is invalid (empty, more than 32 grants, a grant without operations or with more than 5, or a `token`, `acl` or `jwt` resource). `envoy.invalid_namespace_name`: the `namespace` value is not a DNS label of 1 to 63 lowercase letters, digits and hyphens. +`validation.invalid_input`: the subject exceeds 256 UTF-8 bytes, the duration is outside the allowed range, or the grant set is invalid (empty, more than 32 grants, a grant without operations or with more than 5, or a `token` or `jwt` resource). `envoy.invalid_namespace_name`: the `namespace` value is not a DNS label of 1 to 63 lowercase letters, digits and hyphens. | Field | Type | Description | | --- | --- | --- | diff --git a/vendor/api/docs/content/tokens/inspect.mdx b/vendor/api/docs/content/tokens/inspect.mdx index 8500a974..56bb5026 100644 --- a/vendor/api/docs/content/tokens/inspect.mdx +++ b/vendor/api/docs/content/tokens/inspect.mdx @@ -24,7 +24,7 @@ curl "https://rivet.example.com/auth/tokens/inspect" \ ## Authentication -Send the namespace token to inspect as a bearer token in the `Authorization` header. The admin token is rejected. See [Authentication](/docs/api/authentication). +Send your namespace token as a bearer token in the `Authorization` header. Every control plane request also requires the `namespace` query parameter. See [Authentication](/docs/api/authentication). ## Responses @@ -34,8 +34,8 @@ The token's claims. The response carries `Cache-Control: no-store`. | Field | Type | Description | | --- | --- | --- | -| `namespace` | `string` | Namespace the token is scoped to. | -| `subject` | `string \| null` | Subject attached to the token, or `null`. | +| `namespace` | `string` | Name of the namespace to operate in. | +| `subject` | `string \| null` | Subject attached to the token, if any. | | `grants` | `object[]` | Permissions the token carries. | | `grants[].resource` | `"namespace" \| "actor" \| "node" \| "pool" \| "datacenter" \| "actor_gateway" \| "actor_kv"` | Resource type the grant applies to. | | `grants[].target` | `"any" \| object` | `"any"` for every resource of this type, or `{ "id": "..." }` for one resource. | diff --git a/vendor/api/docs/content/worker-connect.mdx b/vendor/api/docs/content/worker-connect.mdx index eff92982..616be0a6 100644 --- a/vendor/api/docs/content/worker-connect.mdx +++ b/vendor/api/docs/content/worker-connect.mdx @@ -26,8 +26,6 @@ The token travels as a `rivet_token.{token}` subprotocol, the same as other WebS Messages are binary [BARE](https://baremessages.org/) frames. The schema, versioned message types, and a reference client live in the repository: -- [Protocol schemas](https://github.com/rivet-dev/rivet/tree/main/engine/sdks/schemas/envoy-protocol), one `.bare` file per protocol version +- [Protocol schemas](https://github.com/rivet-dev/rivet/tree/main/engine/sdks/rust/envoy-protocol/schemas), one `.bare` file per protocol version - [Rust protocol types](https://github.com/rivet-dev/rivet/tree/main/engine/sdks/rust/envoy-protocol) generated from the schemas - [Rust client](https://github.com/rivet-dev/rivet/tree/main/engine/sdks/rust/envoy-client), the transport rivetkit-core uses to hold this connection - -To see which nodes are connected, use [List Nodes](/docs/api/pools/list-nodes). diff --git a/vendor/api/docs/endpoints.json b/vendor/api/docs/endpoints.json index f004f2a8..c605faab 100644 --- a/vendor/api/docs/endpoints.json +++ b/vendor/api/docs/endpoints.json @@ -1,1334 +1,892 @@ { - "$comment": "Source of truth for the generated HTTP API reference. Run `node scripts/docs/gen-api-reference.mjs` after editing.", - "baseUrl": "https://rivet.example.com", - "specs": { - "engine": { - "file": "engine/artifacts/openapi.json", - "auth": { - "curlHeaders": [ - "Authorization: Bearer $RIVET_TOKEN" - ], - "description": "Send the admin token, or a namespace token from [Create Token](/docs/api/tokens/create) whose grants cover the request, as a bearer token in the `Authorization` header. The `x-rivet-token` header is also accepted. Routes with a `namespace` query parameter use the `default` namespace when it is omitted. See [Authentication](/docs/api/authentication)." - }, - "parameters": { - "namespace": "Name of the namespace to operate in. Defaults to `default`.", - "actor_id": "ID of the actor.", - "limit": "Maximum number of results to return, from 1 to 100. Defaults to 100.", - "cursor": "Pagination cursor. Pass the `pagination.cursor` value from the previous response to fetch the next page.", - "pagination.cursor": "Cursor for the next page, or `null` when there are no more results.", - "actor.actor_id": "Unique ID of the actor.", - "actor.name": "Actor name as registered in your RivetKit registry.", - "actor.key": "Actor key. Multi-part keys are joined with `/`, see [Actor Keys](/docs/api/actor-keys). An empty string for an actor without a key.", - "actor.runner_name_selector": "Node pool the actor runs in.", - "actors[].actor_id": "Unique ID of the actor.", - "actors[].name": "Actor name as registered in your RivetKit registry.", - "actors[].key": "Actor key. Multi-part keys are joined with `/`, see [Actor Keys](/docs/api/actor-keys). An empty string for an actor without a key.", - "actors[].runner_name_selector": "Node pool the actor runs in.", - "names": "Map of actor name to metadata.", - "token": "The issued token. Treat it as a secret.", - "issued_ts": "When the token was issued, in Unix milliseconds.", - "expires_ts": "When the token expires, in Unix milliseconds.", - "subject": "Subject attached to the token, or `null`.", - "grants": "Permissions the token carries.", - "grants[].resource": "Resource type the grant applies to.", - "grants[].target": "`\"any\"` for every resource of this type, or `{ \"id\": \"...\" }` for one resource.", - "grants[].operations": "Operations the token may perform on the target." - }, - "authProfiles": { - "none": { - "curlHeaders": [], - "description": "No authentication is required." - }, - "admin": { - "curlHeaders": [ - "Authorization: Bearer $RIVET_TOKEN" - ], - "description": "Requires the admin token, sent as a bearer token in the `Authorization` header. Namespace tokens are rejected. See [Authentication](/docs/api/authentication)." - }, - "token": { - "curlHeaders": [ - "Authorization: Bearer $RIVET_TOKEN" - ], - "description": "Send the namespace token to inspect as a bearer token in the `Authorization` header. The admin token is rejected. See [Authentication](/docs/api/authentication)." - } - } - }, - "rivetkit": { - "file": "rivetkit-openapi/openapi.json", - "auth": { - "curlHeaders": [ - "x-rivet-token: $RIVET_TOKEN" - ], - "description": "Send a token in the `x-rivet-token` header, inline in the path as `{actor_id}@{token}`, or in the `rvt-token` query parameter. Use a [scoped token](/docs/jwt) from browsers and your Rivet token from trusted backends. See [Authentication](/docs/api/authentication)." - }, - "parameters": { - "actor": "Actor ID, actor ID with an inline token (`{actor_id}@{token}`), or actor name combined with the `rvt-*` query parameters.", - "rvt-namespace": "Namespace the actor lives in. Required when `{actor}` is an actor name.", - "rvt-method": "How to resolve an actor name to an actor. `getOrCreate` requires `rvt-pool`.", - "rvt-key": "Actor key. Separate multi-part keys with commas.", - "rvt-pool": "Pool to create the actor on when `rvt-method=getOrCreate`. RivetKit registers the `default` pool unless configured otherwise.", - "rvt-runner": "Deprecated alias for `rvt-pool`.", - "rvt-input": "Base64url-encoded CBOR input passed to `createState` and `onCreate` when `rvt-method=getOrCreate` creates the actor.", - "rvt-region": "Preferred region when `rvt-method=getOrCreate` creates the actor.", - "rvt-crash-policy": "Crash policy when `rvt-method=getOrCreate` creates the actor. RivetKit defaults to `sleep`.", - "rvt-skip-ready-wait": "Return as soon as the actor is resolved instead of waiting for it to be ready.", - "rvt-token": "Token to authenticate with. Prefer the `x-rivet-token` header or inline path token when possible.", - "args": "Positional arguments passed to the action, in order.", - "output": "Value returned by the action. `null` if the action returned `undefined`." - }, - "authProfiles": { - "inspector": { - "curlHeaders": [ - "Authorization: Bearer $INSPECTOR_TOKEN" - ], - "description": "Inspector endpoints do not accept namespace tokens. Send the actor's inspector token as a bearer token in the `Authorization` header. {/* TODO(code): document how to read an Actor's inspector token once an API returns it (ACT-6493). */}" - } - } - }, - "asyncapi": { - "file": "rivetkit-asyncapi/asyncapi.json" - } - }, - "errorCodes": { - "artifacts": "engine/artifacts/errors", - "exclude": [ - "test" - ], - "output": "error-registry.json", - "statusSources": [ - { - "label": "gateway", - "file": "engine/packages/guard-core/src/errors.rs" - }, - { - "label": "control plane", - "file": "engine/packages/api-public-shim/src/lib.rs" - }, - { - "label": "gateway", - "file": "rivetkit-rust/packages/rivetkit-core/src/registry/http.rs" - }, - { - "label": "gateway", - "file": "rivetkit-rust/packages/rivetkit-core/src/error.rs" - } - ], - "groups": { - "actor": "Actor lifecycle, addressing, and actions.", - "api": "Malformed requests to the control plane.", - "auth": "Token validation and permissions.", - "connection": "Actor connections opened through the connection protocol.", - "envoy": "Node connections, and validation of namespace and pool names.", - "guard": "The gateway that routes requests to actors, including request parsing, rate limits, and timeouts.", - "message": "Message size limits on connections.", - "namespace": "Namespace lookup and creation.", - "pool": "Node pool configuration.", - "protocol": "Encoding and framing of connection protocol messages.", - "queue": "Actor queues.", - "user": "Errors thrown by your actor code. The code is whatever you pass to `UserError`.", - "validation": "Request validation.", - "ws": "WebSocket handling for the connection protocol and `onWebSocket` handlers." - } - }, - "groups": [ - { - "title": "General", - "pages": [ - { - "title": "Overview", - "href": "/docs/api", - "icon": "faSquareInfo" - }, - { - "title": "Authentication", - "href": "/docs/api/authentication", - "icon": "faKey" - }, - { - "title": "Actor Keys", - "href": "/docs/api/actor-keys", - "icon": "faIdCard" - }, - { - "title": "Actor Routing", - "href": "/docs/api/actor-routing", - "icon": "faRoute" - }, - { - "title": "Errors", - "href": "/docs/api/errors", - "icon": "faTriangleExclamation" - }, - { - "title": "Error Codes", - "href": "/docs/api/error-codes", - "icon": "faListUl" - } - ] - }, - { - "title": "Manage Actors", - "dir": "actors", - "endpoints": [ - { - "spec": "engine", - "method": "get", - "path": "/actors", - "slug": "list", - "title": "List Actors", - "description": "List actors in a namespace by ID, by name and key, or by name. Listings by name are paginated.", - "notes": "Pass `actor_ids` (comma-separated) to look up actors by ID, or `name` with an optional `key`. `actor_ids` takes precedence over `name` and `key`. Only a listing by `name` without `key` is paginated; a page can hold fewer than `limit` actors while `pagination.cursor` is still set. Destroyed actors are excluded unless `include_destroyed` is `true`. A namespace token needs a grant on `actor` with `list`.", - "typescript": "examples/docs/api/actors-list.ts", - "parameters": { - "name": "Only return actors with this name. Required unless `actor_ids` or `actor_id` is set.", - "key": "Only return the actor with this key. Requires `name`. Multi-part keys are joined with `/`, see [Actor Keys](/docs/api/actor-keys).", - "actor_ids": "Comma-separated IDs of the actors to return.", - "actor_id": "Same as `actor_ids`. Used only when `actor_ids` is absent.", - "include_destroyed": "Include destroyed actors. Must be `true` or `false`." - }, - "examples": { - "query": { - "namespace": "$RIVET_NAMESPACE", - "name": "counter" - } - }, - "responses": { - "200": "Matching actors and a cursor for the next page. `pagination.cursor` is `null` on the last page." - } - }, - { - "spec": "engine", - "method": "get", - "path": "/actors/{actor_id}", - "slug": "get", - "title": "Get Actor", - "description": "Get a live actor by ID.", - "notes": "Returns `actor.not_found` for an actor that was destroyed or belongs to another namespace. A namespace token needs a grant on `actor` with `read`.", - "examples": { - "query": { - "namespace": "$RIVET_NAMESPACE" - } - }, - "responses": { - "200": "The actor." - } - }, - { - "spec": "engine", - "method": "post", - "path": "/actors", - "slug": "create", - "title": "Create Actor", - "description": "Create a new actor. Fails if a live actor with the same name and key already exists.", - "notes": "Prefer [Get or Create Actor](/docs/api/actors/get-or-create) for idempotent access by key. Use this endpoint when you need a fresh actor every time, for example with a random key. The request returns once the actor's record exists, and fails after 30 seconds. A namespace token needs a grant on `actor` with `create`.", - "typescript": "examples/docs/api/actors-create.ts", - "parameters": { - "name": "Name of the actor as registered in your RivetKit registry. 1 to 64 bytes.", - "key": "Key identifying this actor within its name. Multi-part keys are joined with `/`, see [Actor Keys](/docs/api/actor-keys). Omit for an actor without a key.", - "runner_name_selector": "Node pool that runs the actor. Defaults to `default`.", - "input": "Input passed to the actor, encoded as standard base64 (not base64url)." - }, - "examples": { - "query": { - "namespace": "$RIVET_NAMESPACE" - }, - "body": { - "name": "counter", - "key": "my-counter", - "runner_name_selector": "default" - } - }, - "responses": { - "200": "The created actor. `created` is always `true`." - } - }, - { - "spec": "engine", - "method": "put", - "path": "/actors", - "slug": "get-or-create", - "title": "Get or Create Actor", - "description": "Return the actor with the given name and key, creating it if it does not exist. This is the HTTP equivalent of client.actor.getOrCreate(key).", - "notes": "The response includes `created`, which is `true` when this call created the actor. A sleeping actor is woken. Without `key`, a new actor is created every time. Gateway endpoints can perform the same lookup inline with the `rvt-*` selector parameters, so you only need this endpoint when you want the `actor_id` up front. A namespace token needs a grant on `actor` with `create`.", - "typescript": "examples/docs/api/actors-get-or-create.ts", - "parameters": { - "name": "Name of the actor as registered in your RivetKit registry. 1 to 64 bytes.", - "key": "Key identifying this actor within its name. Multi-part keys are joined with `/`, see [Actor Keys](/docs/api/actor-keys).", - "runner_name_selector": "Node pool that runs the actor. Defaults to `default`.", - "input": "Input passed to the actor if this request creates it, encoded as standard base64 (not base64url)." - }, - "examples": { - "query": { - "namespace": "$RIVET_NAMESPACE" - }, - "body": { - "name": "counter", - "key": "my-counter", - "runner_name_selector": "default" - } - } - }, - { - "spec": "engine", - "method": "delete", - "path": "/actors/{actor_id}", - "slug": "destroy", - "title": "Destroy Actor", - "description": "Destroy an actor. The actor's onDestroy hook runs, then its state is deleted permanently.", - "typescript": "examples/docs/api/actors-destroy.ts", - "examples": { - "query": { - "namespace": "$RIVET_NAMESPACE" - } - }, - "related": [ - { - "title": "Destroying Actors", - "href": "/actors/docs/destroy" - } - ], - "notes": "A namespace token needs a grant on `actor` with `delete`.", - "responses": { - "200": "The destroy was accepted. The response body is an empty object." - } - }, - { - "spec": "engine", - "method": "post", - "path": "/actors/{actor_id}/sleep", - "slug": "sleep", - "title": "Sleep Actor", - "description": "Put an actor to sleep. The actor runs its shutdown sequence and persists its state, then wakes on the next request.", - "typescript": "examples/docs/api/actors-sleep.ts", - "examples": { - "query": { - "namespace": "$RIVET_NAMESPACE" - } - }, - "related": [ - { - "title": "Lifecycle", - "href": "/actors/docs/lifecycle" - } - ], - "notes": "The request body is ignored. A namespace token needs a grant on `actor` with `update`.", - "responses": { - "200": "The sleep was accepted. The response body is an empty object." - } - }, - { - "spec": "engine", - "method": "post", - "path": "/actors/{actor_id}/reschedule", - "slug": "reschedule", - "title": "Reschedule Actor", - "description": "Move an actor to a new allocation. A running actor is stopped and starts again, possibly on another node, with its persisted state.", - "typescript": "examples/docs/api/actors-reschedule.ts", - "examples": { - "query": { - "namespace": "$RIVET_NAMESPACE" - } - }, - "related": [ - { - "title": "Lifecycle", - "href": "/actors/docs/lifecycle" - } - ], - "notes": "A running or stopping actor is stopped and allocated again, and a sleeping actor is allocated now. An actor that is still starting, or is destroyed, is left as is and the request still succeeds. The request body is ignored. A namespace token needs a grant on `actor` with `update`.", - "responses": { - "200": "The reschedule was accepted, or there was nothing to move. The response body is an empty object." - } - }, - { - "spec": "engine", - "method": "get", - "path": "/actors/names", - "slug": "list-names", - "title": "List Actor Names", - "description": "List the actor names that the namespace's connected nodes accept.", - "typescript": "examples/docs/api/actors-list-names.ts", - "examples": { - "query": { - "namespace": "$RIVET_NAMESPACE" - } - }, - "notes": "A namespace token needs a grant on `actor` with `list`.", - "responses": { - "200": "Map of actor name to metadata." - } - } - ] - }, - { - "title": "Call Actors", - "dir": "gateway", - "spec": "asyncapi", - "endpoints": [ - { - "spec": "rivetkit", - "method": "post", - "path": "/gateway/{actor}/action/{action}", - "slug": "call-action", - "title": "Call Action", - "description": "Invoke an action defined on an actor and return its result. This is the HTTP equivalent of calling a method on an actor handle in the RivetKit client.", - "notes": "Arguments are passed as a JSON array in `args` and spread into the action's parameters. The action's return value comes back in `output`. Actions that return `undefined` respond with `{ \"output\": null }`.", - "typescript": "examples/docs/api/gateway-call-action.ts", - "parameters": { - "action": "Name of the action as defined in the actor's `actions` map." - }, - "examples": { - "path": { - "actor": "counter", - "action": "increment" - }, - "selector": { - "rvt-namespace": "$RIVET_NAMESPACE", - "rvt-method": "getOrCreate", - "rvt-key": "my-counter", - "rvt-pool": "default" - }, - "body": { - "args": [ - 1 - ] - }, - "response": { - "output": 1 - } - }, - "related": [ - { - "title": "Actions", - "href": "/actors/docs/actions" - }, - { - "title": "Actor Routing", - "href": "/docs/api/actor-routing" - } - ] - }, - { - "spec": "rivetkit", - "method": "any", - "path": "/gateway/{actor}/request/{path}", - "slug": "request", - "title": "Raw HTTP Request", - "description": "Forward a raw HTTP request to an actor's onRequest handler. The method, headers, body, and the path after /request/ are passed through unchanged.", - "notes": "Use this when an actor exposes its own HTTP routes, streams responses (for example Server-Sent Events), or needs to accept non-JSON payloads. The response is whatever the actor's `onRequest` handler returns.", - "typescript": "examples/docs/api/gateway-request.ts", - "parameters": { - "path": "Path forwarded to the actor. The actor sees a request whose URL path is `/{path}`." - }, - "examples": { - "method": "post", - "path": { - "actor": "counter", - "path": "increment" - }, - "selector": { - "rvt-namespace": "$RIVET_NAMESPACE", - "rvt-method": "getOrCreate", - "rvt-key": "my-counter", - "rvt-pool": "default" - } - }, - "responses": { - "200": "The response returned by the actor's `onRequest` handler." - }, - "related": [ - { - "title": "Low-Level HTTP Handler", - "href": "/actors/docs/request-handler" - }, - { - "title": "Raw WebSocket", - "href": "/docs/api/websockets" - } - ] - }, - { - "spec": "rivetkit", - "method": "get", - "path": "/gateway/{actor}/health", - "slug": "health", - "title": "Check Health", - "description": "Check that an actor is reachable through the gateway. Resolves the actor, waits for it to be ready unless rvt-skip-ready-wait is set, and returns a plain-text ok.", - "typescript": "examples/docs/api/gateway-health.ts", - "examples": { - "path": { - "actor": "$ACTOR_ID" - } - }, - "responses": { - "200": "The actor is running and reachable. Body is the text `ok`." - }, - "after": "connect" - }, - { - "spec": "rivetkit", - "method": "post", - "path": "/gateway/{actor}/queue/{name}", - "slug": "queue", - "title": "Send Queue Message", - "description": "Enqueue a durable message for an actor. Optionally wait for the actor to complete it and return a response.", - "notes": "By default, the request returns after the message is enqueued. Set `wait` to `true` to wait for `message.complete(...)`; `timeout` sets that wait in milliseconds, and a timeout returns `status: \"timedOut\"` without canceling the queued work.", - "typescript": "examples/docs/api/gateway-queue.ts", - "parameters": { - "name": "Name of the queue message as defined in the actor's `queues` map." - }, - "examples": { - "path": { - "actor": "counter", - "name": "increment" - }, - "selector": { - "rvt-namespace": "$RIVET_NAMESPACE", - "rvt-method": "getOrCreate", - "rvt-key": "my-counter", - "rvt-pool": "default" - }, - "body": { - "body": { - "amount": 1 - }, - "wait": true, - "timeout": 5000 - }, - "response": { - "status": "completed", - "response": { - "count": 1 - } - } - }, - "responses": { - "200": "The message was enqueued, with its completion status when waiting." - }, - "related": [ - { - "title": "Queues", - "href": "/actors/docs/queues" - } - ], - "after": "call-action" - }, - { - "spec": "rivetkit", - "method": "get", - "path": "/gateway/{actor}/metadata", - "slug": "metadata", - "title": "Get Runtime Metadata", - "description": "Identify the RivetKit runtime serving an actor.", - "typescript": "examples/docs/api/gateway-metadata.ts", - "examples": { - "path": { - "actor": "$ACTOR_ID" - }, - "response": { - "runtime": "rivetkit", - "version": "1.0.0", - "type": "native" - } - }, - "responses": { - "200": "Runtime name, version, and runtime type." - }, - "after": "health" - } - ], - "protocol": [ - { - "slug": "connect", - "title": "Connect", - "description": "Open a persistent WebSocket connection to an actor. One connection carries action calls, event subscriptions, and errors as JSON messages, which is what handle.connect() does in the RivetKit client.", - "url": "wss://rivet.example.com/gateway/{actor}/connect", - "notes": "`{actor}` accepts the same forms as every gateway endpoint: an actor ID, `{actor_id}@{token}`, or an actor name with `rvt-*` query parameters. See [Actor Routing](/docs/api/actor-routing).\n\nConnection options travel as WebSocket subprotocols in the `Sec-WebSocket-Protocol` header because browsers cannot set arbitrary headers on an upgrade. Always include `rivet`, then add any of the prefixed entries below.\n\n| Subprotocol | Purpose |\n| --- | --- |\n| `rivet` | Required. Lets servers that insist on a matching protocol accept the upgrade. |\n| `rivet_encoding.json` | Message encoding. `json` is the default and is documented here. The RivetKit client uses `cbor` or `bare`; the payloads are the same, only the framing differs. |\n| `rivet_token.{token}` | Token to authenticate with. See [WebSocket Requests](/docs/api/authentication#websocket-requests). |\n| `rivet_conn_params.{params}` | Optional connection parameters passed to the actor's `createConnState` and `onBeforeConnect` hooks, as URL-encoded JSON. |\n| `rivet_skip_ready_wait` | Complete the upgrade as soon as the actor is resolved instead of waiting for it to be ready. |\n\nEvery message in both directions is a JSON object of the form `{ \"body\": { \"tag\": \"\", \"val\": { ... } } }`. The server sends `Init` first; nothing else arrives before it. There is no ping or heartbeat message. Rely on WebSocket ping frames or your own timeout to detect a dead connection.", - "sections": [ - { - "title": "Handshake", - "notes": "After the upgrade completes, the server sends `Init` before any other message. Store `connectionId` if you need to correlate connection-scoped state; nothing else needs to be sent before calling actions or subscribing to events.", - "messages": [ - "Init" - ], - "snippets": [ - { - "file": "examples/docs/api/connection-connect.ts", - "title": "WebSocket" - }, - { - "file": "examples/docs/api/connection-connect-client.ts", - "title": "TypeScript" - } - ] - }, - { - "title": "Actions", - "notes": "Send an `ActionRequest` with a client-chosen `id`. The server answers with an `ActionResponse` carrying the same `id`, or with an [`Error`](#errors) whose `actionId` matches. Requests may be pipelined; responses are not guaranteed to arrive in order, so match on `id` rather than position.\n\nThis is the connection equivalent of [Call Action](/docs/api/gateway/call-action) over HTTP. Actions called on a connection can also read connection state set in `createConnState`.", - "messages": [ - "ActionRequest", - "ActionResponse" - ], - "snippets": [ - { - "file": "examples/docs/api/connection-actions.ts", - "title": "WebSocket" - }, - { - "file": "examples/docs/api/connection-actions-client.ts", - "title": "TypeScript" - } - ] - }, - { - "title": "Events", - "notes": "Send a `SubscriptionRequest` with `subscribe: true` to start receiving `Event` messages for an event name, and `subscribe: false` to stop. Subscriptions are per connection and are lost when the connection closes, so resubscribe after reconnecting. The server does not acknowledge subscription changes. If the actor rejects a subscription, the connection is closed with the error as the close reason.\n\nEvents sent by the actor to a connection that has not subscribed to that event name are dropped.", - "messages": [ - "SubscriptionRequest", - "Event" - ], - "snippets": [ - { - "file": "examples/docs/api/connection-events.ts", - "title": "WebSocket" - }, - { - "file": "examples/docs/api/connection-events-client.ts", - "title": "TypeScript" - } - ] - }, - { - "title": "Errors", - "notes": "Errors on an established connection arrive as `Error` messages. `actionId` is set when the error answers a specific `ActionRequest` and `null` for connection-level errors such as a malformed message. The `group` and `code` values are the same ones the HTTP API returns; see [Error Codes](/docs/api/error-codes).\n\nErrors that prevent the connection from being established, such as an invalid token or an actor that does not exist, are reported by closing the WebSocket with a reason of the form `{group}.{code}#{ray_id}`. See [WebSockets](/docs/api/websockets#close-codes).", - "messages": [ - "Error" - ], - "snippets": [ - { - "file": "examples/docs/api/connection-errors.ts", - "title": "WebSocket" - }, - { - "file": "examples/docs/api/connection-errors-client.ts", - "title": "TypeScript" - } - ] - } - ], - "fields": { - "Init.actorId": "ID of the actor this connection is attached to.", - "Init.connectionId": "ID of this connection. Matches `c.conn.id` inside the actor.", - "ActionRequest.id": "Client-chosen identifier used to match the response. Any integer that is unique among in-flight requests on this connection.", - "ActionRequest.name": "Name of the action as defined in the actor's `actions` map.", - "ActionRequest.args": "Positional arguments passed to the action, as a JSON array.", - "ActionResponse.id": "The `id` from the matching `ActionRequest`.", - "ActionResponse.output": "Value returned by the action. `null` if the action returned `undefined`.", - "SubscriptionRequest.eventName": "Name of the event as defined in the actor's `events` map.", - "SubscriptionRequest.subscribe": "`true` to subscribe, `false` to unsubscribe.", - "Event.name": "Name of the event.", - "Event.args": "Arguments passed to `c.broadcast()` or `conn.send()`, as a JSON array.", - "Error.group": "Subsystem that produced the error, such as `actor`, `auth`, or `user`.", - "Error.code": "Error identifier within the group.", - "Error.message": "Human-readable explanation. Do not match on it.", - "Error.metadata": "Structured details attached by the actor or gateway, if any.", - "Error.actionId": "`id` of the `ActionRequest` this error answers, or `null` for connection-level errors.", - "Error.actor": "Actor that handled the message, when known.", - "Error.actor.actorId": "ID of the actor.", - "Error.actor.generation": "Generation of the actor process. Increments each time the actor restarts.", - "Error.actor.key": "Key of the actor, if it has one." - }, - "examples": { - "Init": { - "actorId": "00000000-0000-0000-0000-000000000000", - "connectionId": "00000000-0000-0000-0000-000000000000" - }, - "ActionRequest": { - "id": 1, - "name": "increment", - "args": [ - 1 - ] - }, - "ActionResponse": { - "id": 1, - "output": 1 - }, - "SubscriptionRequest": { - "eventName": "countChanged", - "subscribe": true - }, - "Event": { - "name": "countChanged", - "args": [ - 1 - ] - }, - "Error": { - "group": "user", - "code": "insufficient_funds", - "message": "Balance is too low.", - "metadata": { - "balance": 5 - }, - "actionId": 1, - "actor": { - "actorId": "00000000-0000-0000-0000-000000000000", - "generation": 1, - "key": "my-counter" - } - } - }, - "related": [ - { - "title": "Connections", - "href": "/actors/docs/connections" - }, - { - "title": "Actions", - "href": "/actors/docs/actions" - }, - { - "title": "Events", - "href": "/actors/docs/events" - }, - { - "title": "Errors", - "href": "/docs/api/errors" - }, - { - "title": "Call Action over HTTP", - "href": "/docs/api/gateway/call-action" - }, - { - "title": "Raw WebSocket", - "href": "/docs/api/websockets" - }, - { - "title": "AsyncAPI specification", - "href": "https://github.com/rivet-dev/rivet/tree/main/rivetkit-asyncapi" - } - ] - } - ], - "pages": [ - { - "title": "Raw WebSocket", - "href": "/docs/api/websockets", - "badge": "WS", - "after": "request" - } - ], - "children": [ - { - "title": "Inspector", - "dir": "inspector", - "icon": "faMagnifyingGlass", - "notes": "These endpoints power the actor inspector.", - "endpoints": [ - { - "spec": "rivetkit", - "method": "get", - "path": "/gateway/{actor}/inspector/summary", - "slug": "summary", - "title": "Get Summary", - "description": "Get an overview of an actor's state, connections, actions, queue, database, and workflow.", - "auth": "inspector", - "typescript": "examples/docs/api/inspector-summary.ts", - "examples": { - "path": { - "actor": "$ACTOR_ID" - } - }, - "responses": { - "200": "The actor inspector summary.", - "401": "The inspector token is missing or invalid." - } - }, - { - "spec": "rivetkit", - "method": "get", - "path": "/gateway/{actor}/inspector/state", - "slug": "state-get", - "title": "Get State", - "description": "Read the actor's current state.", - "auth": "inspector", - "typescript": "examples/docs/api/inspector-state-get.ts", - "examples": { - "path": { - "actor": "$ACTOR_ID" - }, - "response": { - "state": { - "count": 1 - } - } - }, - "responses": { - "200": "The current actor state.", - "401": "The inspector token is missing or invalid." - } - }, - { - "spec": "rivetkit", - "method": "patch", - "path": "/gateway/{actor}/inspector/state", - "slug": "state-patch", - "title": "Patch State", - "description": "Replace the actor's current state.", - "notes": "This writes state directly and bypasses actor actions. Use it only for inspection and recovery.", - "auth": "inspector", - "typescript": "examples/docs/api/inspector-state-patch.ts", - "examples": { - "path": { - "actor": "$ACTOR_ID" - }, - "body": { - "state": { - "count": 2 - } - }, - "response": { - "ok": true - } - }, - "responses": { - "200": "The state was saved.", - "401": "The inspector token is missing or invalid." - } - }, - { - "spec": "rivetkit", - "method": "get", - "path": "/gateway/{actor}/inspector/connections", - "slug": "connections", - "title": "List Connections", - "description": "List the actor's active connections.", - "auth": "inspector", - "typescript": "examples/docs/api/inspector-connections.ts", - "examples": { - "path": { - "actor": "$ACTOR_ID" - } - }, - "responses": { - "200": "The active connections.", - "401": "The inspector token is missing or invalid." - } - }, - { - "spec": "rivetkit", - "method": "get", - "path": "/gateway/{actor}/inspector/rpcs", - "slug": "rpcs", - "title": "List Actions", - "description": "List the actions exposed by the actor.", - "auth": "inspector", - "typescript": "examples/docs/api/inspector-rpcs.ts", - "examples": { - "path": { - "actor": "$ACTOR_ID" - } - }, - "responses": { - "200": "The actor's action definitions.", - "401": "The inspector token is missing or invalid." - } - }, - { - "spec": "rivetkit", - "method": "post", - "path": "/gateway/{actor}/inspector/action/{name}", - "slug": "action", - "title": "Invoke Action", - "description": "Invoke an actor action through the inspector.", - "auth": "inspector", - "typescript": "examples/docs/api/inspector-action.ts", - "parameters": { - "name": "Name of the action to invoke." - }, - "examples": { - "path": { - "actor": "$ACTOR_ID", - "name": "increment" - }, - "body": { - "args": [ - 1 - ] - }, - "response": { - "output": 1 - } - }, - "responses": { - "200": "The action result.", - "401": "The inspector token is missing or invalid." - } - }, - { - "spec": "rivetkit", - "method": "get", - "path": "/gateway/{actor}/inspector/queue", - "slug": "queue-get", - "title": "Get Queue", - "description": "List pending queue messages and queue capacity details.", - "auth": "inspector", - "typescript": "examples/docs/api/inspector-queue-get.ts", - "examples": { - "path": { - "actor": "$ACTOR_ID" - }, - "query": { - "limit": 50 - } - }, - "responses": { - "200": "Queue size, capacity, truncation status, and pending message metadata.", - "401": "The inspector token is missing or invalid." - } - }, - { - "spec": "rivetkit", - "method": "post", - "path": "/gateway/{actor}/inspector/queue", - "slug": "queue-post", - "title": "Enqueue Message", - "description": "Enqueue a message through the inspector.", - "auth": "inspector", - "typescript": "examples/docs/api/inspector-queue-post.ts", - "examples": { - "path": { - "actor": "$ACTOR_ID" - }, - "body": { - "name": "increment", - "body": { - "amount": 1 - } - } - }, - "responses": { - "200": "Metadata for the enqueued message.", - "401": "The inspector token is missing or invalid." - } - }, - { - "spec": "rivetkit", - "method": "delete", - "path": "/gateway/{actor}/inspector/queue", - "slug": "queue-delete", - "title": "Clear Queue", - "description": "Remove all pending messages from the actor's queue.", - "auth": "inspector", - "typescript": "examples/docs/api/inspector-queue-delete.ts", - "examples": { - "path": { - "actor": "$ACTOR_ID" - } - }, - "responses": { - "200": "The queue was cleared.", - "401": "The inspector token is missing or invalid." - } - }, - { - "spec": "rivetkit", - "method": "get", - "path": "/gateway/{actor}/inspector/traces", - "slug": "traces", - "title": "Get Traces", - "description": "Get actor trace spans in OTLP JSON format.", - "notes": "Trace collection is not implemented yet, so this route currently returns an empty result.", - "auth": "inspector", - "typescript": "examples/docs/api/inspector-traces.ts", - "examples": { - "path": { - "actor": "$ACTOR_ID" - }, - "query": { - "startMs": 0, - "limit": 100 - } - }, - "responses": { - "200": "Trace data and whether the requested range was clamped.", - "401": "The inspector token is missing or invalid." - } - }, - { - "spec": "rivetkit", - "method": "get", - "path": "/gateway/{actor}/inspector/workflow-history", - "slug": "workflow-history", - "title": "Get Workflow History", - "description": "Read workflow history and whether workflows are enabled for the actor.", - "auth": "inspector", - "typescript": "examples/docs/api/inspector-workflow-history.ts", - "examples": { - "path": { - "actor": "$ACTOR_ID" - } - }, - "responses": { - "200": "Workflow history and availability.", - "401": "The inspector token is missing or invalid." - } - }, - { - "spec": "rivetkit", - "method": "post", - "path": "/gateway/{actor}/inspector/workflow/replay", - "slug": "workflow-replay", - "title": "Replay Workflow", - "description": "Schedule a workflow replay from an optional history entry.", - "auth": "inspector", - "typescript": "examples/docs/api/inspector-workflow-replay.ts", - "examples": { - "path": { - "actor": "$ACTOR_ID" - }, - "body": { - "entryId": "entry-123" - } - }, - "responses": { - "200": "Workflow history after scheduling the replay.", - "401": "The inspector token is missing or invalid." - } - }, - { - "spec": "rivetkit", - "method": "get", - "path": "/gateway/{actor}/inspector/database/schema", - "slug": "database-schema", - "title": "Get Database Schema", - "description": "List tables, views, and columns in the actor's SQLite database.", - "auth": "inspector", - "typescript": "examples/docs/api/inspector-database-schema.ts", - "examples": { - "path": { - "actor": "$ACTOR_ID" - } - }, - "responses": { - "200": "The actor database schema.", - "401": "The inspector token is missing or invalid." - } - }, - { - "spec": "rivetkit", - "method": "get", - "path": "/gateway/{actor}/inspector/database/rows", - "slug": "database-rows", - "title": "Query Database Rows", - "description": "Read a page of rows from an actor database table or view.", - "auth": "inspector", - "typescript": "examples/docs/api/inspector-database-rows.ts", - "examples": { - "path": { - "actor": "$ACTOR_ID" - }, - "query": { - "table": "users", - "limit": 100, - "offset": 0 - } - }, - "responses": { - "200": "The selected rows.", - "401": "The inspector token is missing or invalid." - } - }, - { - "spec": "rivetkit", - "method": "post", - "path": "/gateway/{actor}/inspector/database/execute", - "slug": "database-execute", - "title": "Execute SQL", - "description": "Run a SQL statement against the actor's SQLite database.", - "notes": "SQL executes directly against actor storage. Use bind parameters for values.", - "auth": "inspector", - "typescript": "examples/docs/api/inspector-database-execute.ts", - "examples": { - "path": { - "actor": "$ACTOR_ID" - }, - "body": { - "sql": "SELECT * FROM users WHERE id = ?", - "args": [ - "user-123" - ] - } - }, - "responses": { - "200": "Rows returned by the statement.", - "401": "The inspector token is missing or invalid." - } - } - ], - "pages": [ - { - "title": "Inspector Connect", - "href": "/docs/api/inspector-connect", - "badge": "WS" - } - ], - "notice": "The inspector API is subject to change without notice. Do not build production integrations on it." - } - ] - }, - { - "title": "Tokens", - "dir": "tokens", - "endpoints": [ - { - "spec": "engine", - "method": "post", - "path": "/auth/tokens", - "slug": "create", - "title": "Create Token", - "description": "Issue a scoped token. Use this to mint short-lived tokens that grant a client access to a single actor instead of sharing your namespace token.", - "notes": "Each grant names a resource type, a target (`\"any\"` or a specific `{ \"id\": ... }`), and the operations it allows. A token carries 1 to 32 grants with 1 to 5 operations each. The RivetKit client wraps this as `handle.issueToken()`.", - "typescript": "examples/docs/api/tokens-create.ts", - "parameters": { - "namespace": "Namespace the token is valid in. It must exist.", - "duration": "Lifetime in seconds, from 1 to the deployment's maximum. Omit for the default lifetime.", - "subject": "Free-form subject to attach to the token, such as a user ID. At most 256 UTF-8 bytes.", - "grants": "Permissions the token carries.", - "grants[].resource": "Resource type the grant applies to.", - "grants[].target": "`\"any\"` for every resource of this type, or `{ \"id\": \"...\" }` for one resource.", - "grants[].operations": "Operations the token may perform on the target." - }, - "examples": { - "body": { - "namespace": "my-namespace", - "subject": "user-123", - "duration": 3600, - "grants": [ - { - "resource": "actor_gateway", - "target": { - "id": "d97pbq1nyqxw1w5qdwz0iirbqiblh2" - }, - "operations": [ - "read" - ] - } - ] - } - }, - "auth": "admin" - }, - { - "spec": "engine", - "method": "get", - "path": "/auth/tokens/inspect", - "slug": "inspect", - "title": "Inspect Token", - "description": "Return the namespace, grants, and expiry of the token used to authenticate the request.", - "typescript": "examples/docs/api/tokens-inspect.ts", - "auth": "token", - "parameters": { - "namespace": "Namespace the token is scoped to." - } - } - ] - }, - { - "title": "Namespaces", - "dir": "namespaces", - "endpoints": [ - { - "spec": "engine", - "method": "get", - "path": "/namespaces", - "slug": "list", - "title": "List Namespaces", - "description": "List namespaces in name order, or look up one namespace by name. Results are paginated.", - "notes": "`name` returns zero or one namespace and ignores `limit` and `cursor`. Any other query parameter, including `namespace`, is rejected.", - "typescript": "examples/docs/api/namespaces-list.ts", - "parameters": { - "name": "Only return the namespace with this name." - }, - "responses": { - "200": "Matching namespaces and a cursor for the next page." - }, - "auth": "admin" - }, - { - "spec": "engine", - "method": "post", - "path": "/namespaces", - "slug": "create", - "title": "Create Namespace", - "description": "Create a namespace with a unique name.", - "typescript": "examples/docs/api/namespaces-create.ts", - "parameters": { - "name": "Unique name of the namespace. A DNS label of 1 to 63 lowercase letters, digits and hyphens.", - "namespace": "The created namespace." - }, - "examples": { - "body": { - "name": "my-app" - } - }, - "responses": { - "200": "The newly created namespace." - }, - "auth": "admin" - } - ] - }, - { - "title": "Node Pools", - "dir": "pools", - "endpoints": [ - { - "spec": "engine", - "method": "get", - "path": "/pools", - "slug": "list", - "title": "List Node Pools", - "description": "List the node pools configured in a namespace, ordered by name. Results are paginated.", - "notes": "A pool is listed once it is configured, whether or not any node is connected. A namespace token needs a grant on `pool` with `list`.", - "examples": { - "query": { - "namespace": "$RIVET_NAMESPACE" - } - }, - "responses": { - "200": "A page of node pools and a cursor for the next page." - } - }, - { - "spec": "engine", - "method": "get", - "path": "/pools/{pool}", - "slug": "get", - "title": "Get Node Pool", - "description": "Get a node pool's configuration.", - "notes": "A namespace token needs a grant on `pool` with `read`.", - "examples": { - "path": { - "pool": "default" - }, - "query": { - "namespace": "$RIVET_NAMESPACE" - } - }, - "responses": { - "200": "The node pool." - } - }, - { - "spec": "engine", - "method": "put", - "path": "/pools/{pool}", - "slug": "upsert", - "title": "Upsert Node Pool", - "description": "Create or replace a node pool's configuration.", - "notes": "Every field is optional and omitted fields take their defaults, so a request replaces the whole configuration. Unknown fields are rejected. Serverless pools are not supported. Nodes pick up the new configuration on their next connection. A namespace token needs a grant on `pool` with `update`.", - "examples": { - "path": { - "pool": "default" - }, - "query": { - "namespace": "$RIVET_NAMESPACE" - }, - "body": { - "drain_on_version_upgrade": true, - "actor_eviction_delay": 0, - "actor_eviction_period": 0, - "actor_eviction_rate": 1 - } - }, - "responses": { - "200": "The stored node pool." - } - }, - { - "spec": "engine", - "method": "delete", - "path": "/pools/{pool}", - "slug": "delete", - "title": "Delete Node Pool", - "description": "Delete a node pool's configuration.", - "notes": "Fails with `pool.nodes_connected` while any node of the pool is connected. A namespace token needs a grant on `pool` with `delete`.", - "examples": { - "path": { - "pool": "default" - }, - "query": { - "namespace": "$RIVET_NAMESPACE" - } - }, - "responses": { - "200": "The node pool was deleted. The response body is an empty object." - } - }, - { - "spec": "engine", - "method": "get", - "path": "/pools/{pool}/nodes", - "slug": "list-nodes", - "title": "List Nodes", - "description": "List the live nodes of a node pool in node key order. Results are paginated.", - "notes": "A node is listed while its heartbeat is recent enough for it to receive actors. A page can hold fewer than `limit` nodes while `pagination.cursor` is still set. A namespace token needs a grant on `node` with `list`.", - "examples": { - "path": { - "pool": "default" - }, - "query": { - "namespace": "$RIVET_NAMESPACE" - } - }, - "responses": { - "200": "A page of live nodes and a cursor for the next page." - } - } - ], - "pages": [ - { - "title": "Worker Connection", - "href": "/docs/api/worker-connect", - "badge": "WS", - "after": "list-nodes" - } - ] - }, - { - "title": "Control Plane", - "dir": "control-plane", - "endpoints": [ - { - "spec": "engine", - "method": "get", - "path": "/metadata", - "slug": "metadata", - "title": "Get Metadata", - "description": "Get the runtime and version of the control plane.", - "notes": "A request made with the admin token also receives `actorNames`.", - "typescript": "examples/docs/api/control-plane-metadata.ts", - "auth": "none", - "responses": { - "200": "Runtime and version metadata." - } - }, - { - "spec": "engine", - "method": "get", - "path": "/datacenters", - "slug": "datacenters", - "title": "List Datacenters", - "description": "List the datacenters configured for the control plane.", - "typescript": "examples/docs/api/control-plane-datacenters.ts", - "responses": { - "200": "Configured datacenters." - }, - "notes": "A namespace token needs a grant on `datacenter` with `list`." - } - ] - } - ] + "$comment": "Source of truth for the generated HTTP API reference. Run `node scripts/docs/gen-api-reference.mjs` after editing.", + "baseUrl": "https://rivet.example.com", + "specs": { + "engine": { + "file": "engine/artifacts/openapi.json", + "auth": { + "curlHeaders": [ + "Authorization: Bearer $RIVET_TOKEN" + ], + "description": "Send your namespace token as a bearer token in the `Authorization` header. Every control plane request also requires the `namespace` query parameter. See [Authentication](/docs/api/authentication)." + }, + "parameters": { + "namespace": "Name of the namespace to operate in.", + "actor_id": "ID of the actor.", + "limit": "Maximum number of results to return.", + "cursor": "Pagination cursor. Pass the `pagination.cursor` value from the previous response to fetch the next page.", + "pagination.cursor": "Cursor for the next page, or `null` when there are no more results.", + "actor.actor_id": "Unique ID of the actor.", + "actor.name": "Actor name as registered in your RivetKit registry.", + "actor.key": "Actor key. Multi-part keys are joined with `/`, see [Actor Keys](/docs/api/actor-keys).", + "actor.namespace_id": "ID of the namespace the actor belongs to.", + "actor.datacenter": "Datacenter the actor is scheduled in.", + "actor.runner_name_selector": "Pool the actor runs on.", + "actor.crash_policy": "What happens when the actor crashes.", + "actors[].actor_id": "Unique ID of the actor.", + "actors[].name": "Actor name as registered in your RivetKit registry.", + "actors[].key": "Actor key. Multi-part keys are joined with `/`, see [Actor Keys](/docs/api/actor-keys).", + "actors[].namespace_id": "ID of the namespace the actor belongs to.", + "actors[].datacenter": "Datacenter the actor is scheduled in.", + "actors[].runner_name_selector": "Pool the actor runs on.", + "actors[].crash_policy": "What happens when the actor crashes.", + "created": "`true` if this request created the actor, `false` if it already existed.", + "names": "Map of actor name to metadata.", + "names.metadata": "Free-form metadata attached to the actor name.", + "token": "The issued token. Treat it as a secret.", + "issued_ts": "When the token was issued, in Unix milliseconds.", + "expires_ts": "When the token expires, in Unix milliseconds.", + "namespace_id": "ID of the namespace the token is scoped to.", + "subject": "Subject attached to the token, if any.", + "grants": "Permissions the token carries.", + "grants[].resource": "Resource type the grant applies to.", + "grants[].target": "`\"any\"` for every resource of this type, or `{ \"id\": \"...\" }` for one resource.", + "grants[].operations": "Operations the token may perform on the target.", + "value": "Base64-encoded value bytes.", + "update_ts": "When the key was last written, in Unix milliseconds." + }, + "authProfiles": { + "none": { + "curlHeaders": [], + "description": "No authentication is required." + } + } + }, + "rivetkit": { + "file": "rivetkit-openapi/openapi.json", + "auth": { + "curlHeaders": [ + "x-rivet-token: $RIVET_TOKEN" + ], + "description": "Send a token in the `x-rivet-token` header, inline in the path as `{actor_id}@{token}`, or in the `rvt-token` query parameter. Use a [scoped token](/docs/jwt) from browsers and your Rivet token from trusted backends. See [Authentication](/docs/api/authentication)." + }, + "parameters": { + "actor": "Actor ID, actor ID with an inline token (`{actor_id}@{token}`), or actor name combined with the `rvt-*` query parameters.", + "rvt-namespace": "Namespace the actor lives in. Required when `{actor}` is an actor name.", + "rvt-method": "How to resolve an actor name to an actor. `getOrCreate` requires `rvt-pool`.", + "rvt-key": "Actor key. Separate multi-part keys with commas.", + "rvt-pool": "Pool to create the actor on when `rvt-method=getOrCreate`. RivetKit registers the `default` pool unless configured otherwise.", + "rvt-runner": "Deprecated alias for `rvt-pool`.", + "rvt-input": "Base64url-encoded CBOR input passed to `createState` and `onCreate` when `rvt-method=getOrCreate` creates the actor.", + "rvt-region": "Preferred region when `rvt-method=getOrCreate` creates the actor.", + "rvt-crash-policy": "Crash policy when `rvt-method=getOrCreate` creates the actor. RivetKit defaults to `sleep`.", + "rvt-skip-ready-wait": "Return as soon as the actor is resolved instead of waiting for it to be ready.", + "rvt-token": "Token to authenticate with. Prefer the `x-rivet-token` header or inline path token when possible.", + "args": "Positional arguments passed to the action, in order.", + "output": "Value returned by the action. `null` if the action returned `undefined`." + } + }, + "asyncapi": { + "file": "rivetkit-asyncapi/asyncapi.json" + } + }, + "errorCodes": { + "artifacts": "engine/artifacts/errors", + "exclude": [ + "test" + ], + "output": "error-registry.json", + "statusSources": [ + { + "label": "gateway", + "file": "engine/packages/guard-core/src/errors.rs" + }, + { + "label": "control plane", + "file": "engine/packages/api-builder/src/error_response.rs" + }, + { + "label": "gateway", + "file": "rivetkit-rust/packages/rivetkit-core/src/registry/http.rs" + }, + { + "label": "gateway", + "file": "rivetkit-rust/packages/rivetkit-core/src/error.rs" + } + ], + "groups": { + "actor": "Actor lifecycle, addressing, and actions.", + "api": "Malformed requests to the control plane.", + "auth": "Token validation and permissions.", + "connection": "Actor connections opened through the connection protocol.", + "guard": "The gateway that routes requests to actors, including request parsing, rate limits, and timeouts.", + "kv": "Low-level KV storage inside an actor.", + "message": "Message size limits on connections.", + "namespace": "Namespace lookup and creation.", + "protocol": "Encoding and framing of connection protocol messages.", + "queue": "Actor queues.", + "user": "Errors thrown by your actor code. The code is whatever you pass to `UserError`.", + "validation": "Request validation.", + "ws": "WebSocket handling for the connection protocol and `onWebSocket` handlers." + } + }, + "groups": [ + { + "title": "General", + "pages": [ + { + "title": "Overview", + "href": "/docs/api", + "icon": "faSquareInfo" + }, + { + "title": "Authentication", + "href": "/docs/api/authentication", + "icon": "faKey" + }, + { + "title": "Actor Keys", + "href": "/docs/api/actor-keys", + "icon": "faIdCard" + }, + { + "title": "Actor Routing", + "href": "/docs/api/actor-routing", + "icon": "faRoute" + }, + { + "title": "Errors", + "href": "/docs/api/errors", + "icon": "faTriangleExclamation" + }, + { + "title": "Error Codes", + "href": "/docs/api/error-codes", + "icon": "faListUl" + } + ] + }, + { + "title": "Manage Actors", + "dir": "actors", + "endpoints": [ + { + "spec": "engine", + "method": "get", + "path": "/actors", + "slug": "list", + "title": "List Actors", + "description": "List actors in a namespace, optionally filtered by name, key, or ID. Results are paginated.", + "notes": "`key` requires `name`. `actor_id` cannot be combined with `name` or `key`. Destroyed actors are excluded unless `include_destroyed` is `true`.", + "typescript": "examples/docs/api/actors-list.ts", + "parameters": { + "name": "Only return actors with this name.", + "key": "Only return the actor with this key. Requires `name`. Multi-part keys are joined with `/`, see [Actor Keys](/docs/api/actor-keys).", + "actor_id": "Only return actors with these IDs. Repeat the parameter for multiple IDs.", + "actor_ids": "Deprecated. Use `actor_id` instead.", + "include_destroyed": "Include actors that have been destroyed." + }, + "examples": { + "query": { + "namespace": "$RIVET_NAMESPACE", + "name": "counter" + } + }, + "responses": { + "200": "Matching actors and a cursor for the next page. `pagination.cursor` is `null` on the last page." + } + }, + { + "spec": "engine", + "method": "post", + "path": "/actors", + "slug": "create", + "title": "Create Actor", + "description": "Create a new actor. Fails if an actor with the same name and key already exists.", + "notes": "Prefer [Get or Create Actor](/docs/api/actors/get-or-create) for idempotent access by key. Use this endpoint when you need a fresh actor every time, for example with a random key.", + "typescript": "examples/docs/api/actors-create.ts", + "parameters": { + "name": "Name of the actor as registered in your RivetKit registry.", + "key": "Key identifying this actor within its name. Multi-part keys are joined with `/`, see [Actor Keys](/docs/api/actor-keys). Omit for a keyless actor.", + "runner_name_selector": "Pool that runs the actor. RivetKit registers the `default` pool unless configured otherwise.", + "crash_policy": "What happens when the actor crashes. RivetKit defaults to `sleep`.", + "datacenter": "Datacenter to create the actor in. Defaults to the datacenter serving the request.", + "input": "Base64url-encoded CBOR input passed to the actor's `createState` and `onCreate` hooks." + }, + "examples": { + "query": { + "namespace": "$RIVET_NAMESPACE" + }, + "body": { + "name": "counter", + "key": "my-counter", + "runner_name_selector": "default", + "crash_policy": "sleep" + } + } + }, + { + "spec": "engine", + "method": "put", + "path": "/actors", + "slug": "get-or-create", + "title": "Get or Create Actor", + "description": "Return the actor with the given name and key, creating it if it does not exist. This is the HTTP equivalent of client.actor.getOrCreate(key).", + "notes": "The response includes `created`, which is `true` when this call created the actor. Gateway endpoints can perform the same lookup inline with the `rvt-*` selector parameters, so you only need this endpoint when you want the `actor_id` up front.", + "typescript": "examples/docs/api/actors-get-or-create.ts", + "parameters": { + "name": "Name of the actor as registered in your RivetKit registry.", + "key": "Key identifying this actor within its name. Multi-part keys are joined with `/`, see [Actor Keys](/docs/api/actor-keys).", + "runner_name_selector": "Pool that runs the actor. RivetKit registers the `default` pool unless configured otherwise.", + "crash_policy": "What happens when the actor crashes. RivetKit defaults to `sleep`.", + "datacenter": "Datacenter to create the actor in if it does not exist. Defaults to the datacenter serving the request.", + "input": "Base64url-encoded CBOR input passed to the actor's `createState` and `onCreate` hooks when the actor is created." + }, + "examples": { + "query": { + "namespace": "$RIVET_NAMESPACE" + }, + "body": { + "name": "counter", + "key": "my-counter", + "runner_name_selector": "default", + "crash_policy": "sleep" + } + } + }, + { + "spec": "engine", + "method": "delete", + "path": "/actors/{actor_id}", + "slug": "destroy", + "title": "Destroy Actor", + "description": "Destroy an actor. The actor's onDestroy hook runs, then its state is deleted permanently.", + "typescript": "examples/docs/api/actors-destroy.ts", + "examples": { + "query": { + "namespace": "$RIVET_NAMESPACE" + } + }, + "related": [ + { + "title": "Destroying Actors", + "href": "/actors/docs/destroy" + } + ] + }, + { + "spec": "engine", + "method": "post", + "path": "/actors/{actor_id}/sleep", + "slug": "sleep", + "title": "Sleep Actor", + "description": "Put an actor to sleep. The actor runs its shutdown sequence and persists its state, then wakes on the next request.", + "typescript": "examples/docs/api/actors-sleep.ts", + "examples": { + "query": { + "namespace": "$RIVET_NAMESPACE" + }, + "body": {} + }, + "related": [ + { + "title": "Lifecycle", + "href": "/actors/docs/lifecycle" + } + ] + }, + { + "spec": "engine", + "method": "post", + "path": "/actors/{actor_id}/reschedule", + "slug": "reschedule", + "title": "Reschedule Actor", + "description": "Move an actor to a different worker. The actor runs its shutdown sequence, then restarts elsewhere with its persisted state.", + "typescript": "examples/docs/api/actors-reschedule.ts", + "examples": { + "query": { + "namespace": "$RIVET_NAMESPACE" + }, + "body": {} + }, + "related": [ + { + "title": "Lifecycle", + "href": "/actors/docs/lifecycle" + } + ] + }, + { + "spec": "engine", + "method": "get", + "path": "/actors/names", + "slug": "list-names", + "title": "List Actor Names", + "description": "List the distinct actor names that have been created in a namespace.", + "typescript": "examples/docs/api/actors-list-names.ts", + "examples": { + "query": { + "namespace": "$RIVET_NAMESPACE" + } + } + } + ] + }, + { + "title": "Call Actors", + "dir": "gateway", + "spec": "asyncapi", + "endpoints": [ + { + "spec": "rivetkit", + "method": "post", + "path": "/gateway/{actor}/action/{action}", + "slug": "call-action", + "title": "Call Action", + "description": "Invoke an action defined on an actor and return its result. This is the HTTP equivalent of calling a method on an actor handle in the RivetKit client.", + "notes": "Arguments are passed as a JSON array in `args` and spread into the action's parameters. The action's return value comes back in `output`. Actions that return `undefined` respond with `{ \"output\": null }`.", + "typescript": "examples/docs/api/gateway-call-action.ts", + "parameters": { + "action": "Name of the action as defined in the actor's `actions` map." + }, + "examples": { + "path": { + "actor": "counter", + "action": "increment" + }, + "selector": { + "rvt-namespace": "$RIVET_NAMESPACE", + "rvt-method": "getOrCreate", + "rvt-key": "my-counter", + "rvt-pool": "default" + }, + "body": { + "args": [ + 1 + ] + }, + "response": { + "output": 1 + } + }, + "related": [ + { + "title": "Actions", + "href": "/actors/docs/actions" + }, + { + "title": "Actor Routing", + "href": "/docs/api/actor-routing" + } + ] + }, + { + "spec": "rivetkit", + "method": "get", + "path": "/gateway/{actor}/health", + "slug": "health", + "title": "Check Health", + "description": "Check that an actor is reachable through the gateway. Resolves the actor, waits for it to be ready unless rvt-skip-ready-wait is set, and returns a plain-text ok.", + "typescript": "examples/docs/api/gateway-health.ts", + "examples": { + "path": { + "actor": "$ACTOR_ID" + } + }, + "responses": { + "200": "The actor is running and reachable. Body is the text `ok`." + }, + "after": "connect" + }, + { + "spec": "rivetkit", + "method": "post", + "path": "/gateway/{actor}/queue/{name}", + "slug": "queue", + "title": "Send Queue Message", + "description": "Enqueue a durable message for an actor. Optionally wait for the actor to complete it and return a response.", + "notes": "By default, the request returns after the message is enqueued. Set `wait` to `true` to wait for `message.complete(...)`; `timeout` sets that wait in milliseconds, and a timeout returns `status: \"timedOut\"` without canceling the queued work.", + "typescript": "examples/docs/api/gateway-queue.ts", + "parameters": { + "name": "Name of the queue message as defined in the actor's `queues` map." + }, + "examples": { + "path": { + "actor": "counter", + "name": "increment" + }, + "selector": { + "rvt-namespace": "$RIVET_NAMESPACE", + "rvt-method": "getOrCreate", + "rvt-key": "my-counter", + "rvt-pool": "default" + }, + "body": { + "body": { + "amount": 1 + }, + "wait": true, + "timeout": 5000 + }, + "response": { + "status": "completed", + "response": { + "count": 1 + } + } + }, + "responses": { + "200": "The message was enqueued, with its completion status when waiting." + }, + "related": [ + { + "title": "Queues", + "href": "/actors/docs/queues" + } + ], + "after": "call-action" + }, + { + "spec": "rivetkit", + "method": "get", + "path": "/gateway/{actor}/metadata", + "slug": "metadata", + "title": "Get Runtime Metadata", + "description": "Identify the RivetKit runtime serving an actor.", + "typescript": "examples/docs/api/gateway-metadata.ts", + "examples": { + "path": { + "actor": "$ACTOR_ID" + }, + "response": { + "runtime": "rivetkit", + "version": "1.0.0", + "type": "native" + } + }, + "responses": { + "200": "Runtime name, version, and runtime type." + }, + "after": "health" + } + ], + "protocol": [ + { + "slug": "connect", + "title": "Connect", + "description": "Open a persistent WebSocket connection to an actor. One connection carries action calls, event subscriptions, and errors as JSON messages, which is what handle.connect() does in the RivetKit client.", + "url": "wss://rivet.example.com/gateway/{actor}/connect", + "notes": "`{actor}` accepts the same forms as every gateway endpoint: an actor ID, `{actor_id}@{token}`, or an actor name with `rvt-*` query parameters. See [Actor Routing](/docs/api/actor-routing).\n\nConnection options travel as WebSocket subprotocols in the `Sec-WebSocket-Protocol` header because browsers cannot set arbitrary headers on an upgrade. Always include `rivet`, then add any of the prefixed entries below.\n\n| Subprotocol | Purpose |\n| --- | --- |\n| `rivet` | Required. Lets servers that insist on a matching protocol accept the upgrade. |\n| `rivet_encoding.json` | Message encoding. `json` is the default and is documented here. The RivetKit client uses `cbor` or `bare`; the payloads are the same, only the framing differs. |\n| `rivet_token.{token}` | Token to authenticate with. See [WebSocket Requests](/docs/api/authentication#websocket-requests). |\n| `rivet_conn_params.{params}` | Optional connection parameters passed to the actor's `createConnState` and `onBeforeConnect` hooks, as URL-encoded JSON. |\n| `rivet_skip_ready_wait` | Complete the upgrade as soon as the actor is resolved instead of waiting for it to be ready. |\n\nEvery message in both directions is a JSON object of the form `{ \"body\": { \"tag\": \"\", \"val\": { ... } } }`. The server sends `Init` first; nothing else arrives before it. There is no ping or heartbeat message. Rely on WebSocket ping frames or your own timeout to detect a dead connection.", + "sections": [ + { + "title": "Handshake", + "notes": "After the upgrade completes, the server sends `Init` before any other message. Store `connectionId` if you need to correlate connection-scoped state; nothing else needs to be sent before calling actions or subscribing to events.", + "messages": [ + "Init" + ], + "snippets": [ + { + "file": "examples/docs/api/connection-connect.ts", + "title": "WebSocket" + }, + { + "file": "examples/docs/api/connection-connect-client.ts", + "title": "TypeScript" + } + ] + }, + { + "title": "Actions", + "notes": "Send an `ActionRequest` with a client-chosen `id`. The server answers with an `ActionResponse` carrying the same `id`, or with an [`Error`](#errors) whose `actionId` matches. Requests may be pipelined; responses are not guaranteed to arrive in order, so match on `id` rather than position.\n\nThis is the connection equivalent of [Call Action](/docs/api/gateway/call-action) over HTTP. Actions called on a connection can also read connection state set in `createConnState`.", + "messages": [ + "ActionRequest", + "ActionResponse" + ], + "snippets": [ + { + "file": "examples/docs/api/connection-actions.ts", + "title": "WebSocket" + }, + { + "file": "examples/docs/api/connection-actions-client.ts", + "title": "TypeScript" + } + ] + }, + { + "title": "Events", + "notes": "Send a `SubscriptionRequest` with `subscribe: true` to start receiving `Event` messages for an event name, and `subscribe: false` to stop. Subscriptions are per connection and are lost when the connection closes, so resubscribe after reconnecting. The server does not acknowledge subscription changes. If the actor rejects a subscription, the connection is closed with the error as the close reason.\n\nEvents sent by the actor to a connection that has not subscribed to that event name are dropped.", + "messages": [ + "SubscriptionRequest", + "Event" + ], + "snippets": [ + { + "file": "examples/docs/api/connection-events.ts", + "title": "WebSocket" + }, + { + "file": "examples/docs/api/connection-events-client.ts", + "title": "TypeScript" + } + ] + }, + { + "title": "Errors", + "notes": "Errors on an established connection arrive as `Error` messages. `actionId` is set when the error answers a specific `ActionRequest` and `null` for connection-level errors such as a malformed message. The `group` and `code` values are the same ones the HTTP API returns; see [Error Codes](/docs/api/error-codes).\n\nErrors that prevent the connection from being established, such as an invalid token or an actor that does not exist, are reported by closing the WebSocket with a reason of the form `{group}.{code}#{ray_id}`. See [WebSockets](/docs/api/websockets#close-codes).", + "messages": [ + "Error" + ], + "snippets": [ + { + "file": "examples/docs/api/connection-errors.ts", + "title": "WebSocket" + }, + { + "file": "examples/docs/api/connection-errors-client.ts", + "title": "TypeScript" + } + ] + } + ], + "fields": { + "Init.actorId": "ID of the actor this connection is attached to.", + "Init.connectionId": "ID of this connection. Matches `c.conn.id` inside the actor.", + "ActionRequest.id": "Client-chosen identifier used to match the response. Any integer that is unique among in-flight requests on this connection.", + "ActionRequest.name": "Name of the action as defined in the actor's `actions` map.", + "ActionRequest.args": "Positional arguments passed to the action, as a JSON array.", + "ActionResponse.id": "The `id` from the matching `ActionRequest`.", + "ActionResponse.output": "Value returned by the action. `null` if the action returned `undefined`.", + "SubscriptionRequest.eventName": "Name of the event as defined in the actor's `events` map.", + "SubscriptionRequest.subscribe": "`true` to subscribe, `false` to unsubscribe.", + "Event.name": "Name of the event.", + "Event.args": "Arguments passed to `c.broadcast()` or `conn.send()`, as a JSON array.", + "Error.group": "Subsystem that produced the error, such as `actor`, `auth`, or `user`.", + "Error.code": "Error identifier within the group.", + "Error.message": "Human-readable explanation. Do not match on it.", + "Error.metadata": "Structured details attached by the actor or gateway, if any.", + "Error.actionId": "`id` of the `ActionRequest` this error answers, or `null` for connection-level errors.", + "Error.actor": "Actor that handled the message, when known.", + "Error.actor.actorId": "ID of the actor.", + "Error.actor.generation": "Generation of the actor process. Increments each time the actor restarts.", + "Error.actor.key": "Key of the actor, if it has one." + }, + "examples": { + "Init": { + "actorId": "00000000-0000-0000-0000-000000000000", + "connectionId": "00000000-0000-0000-0000-000000000000" + }, + "ActionRequest": { + "id": 1, + "name": "increment", + "args": [ + 1 + ] + }, + "ActionResponse": { + "id": 1, + "output": 1 + }, + "SubscriptionRequest": { + "eventName": "countChanged", + "subscribe": true + }, + "Event": { + "name": "countChanged", + "args": [ + 1 + ] + }, + "Error": { + "group": "user", + "code": "insufficient_funds", + "message": "Balance is too low.", + "metadata": { + "balance": 5 + }, + "actionId": 1, + "actor": { + "actorId": "00000000-0000-0000-0000-000000000000", + "generation": 1, + "key": "my-counter" + } + } + }, + "related": [ + { + "title": "Connections", + "href": "/actors/docs/connections" + }, + { + "title": "Actions", + "href": "/actors/docs/actions" + }, + { + "title": "Events", + "href": "/actors/docs/events" + }, + { + "title": "Errors", + "href": "/docs/api/errors" + }, + { + "title": "Call Action over HTTP", + "href": "/docs/api/gateway/call-action" + }, + { + "title": "Raw WebSocket", + "href": "/docs/api/websockets" + }, + { + "title": "AsyncAPI specification", + "href": "https://github.com/rivet-dev/rivet/tree/main/rivetkit-asyncapi" + } + ] + } + ], + "pages": [ + { + "title": "Raw WebSocket", + "href": "/docs/api/websockets", + "badge": "WS" + } + ] + }, + { + "title": "Tokens", + "dir": "tokens", + "endpoints": [ + { + "spec": "engine", + "method": "post", + "path": "/auth/tokens", + "slug": "create", + "title": "Create Token", + "description": "Issue a scoped token. Use this to mint short-lived tokens that grant a client access to a single actor instead of sharing your namespace token.", + "notes": "Each grant names a resource type, a target (`\"any\"` or a specific `{ \"id\": ... }`), and the operations it allows. The RivetKit client wraps this as `handle.issueToken()`.", + "typescript": "examples/docs/api/tokens-create.ts", + "parameters": { + "namespace": "Namespace the token is valid in.", + "duration": "Lifetime in seconds. Omit for the default lifetime.", + "subject": "Free-form subject to attach to the token, such as a user ID.", + "grants": "Permissions the token carries.", + "grants[].resource": "Resource type the grant applies to.", + "grants[].target": "`\"any\"` for every resource of this type, or `{ \"id\": \"...\" }` for one resource.", + "grants[].operations": "Operations the token may perform on the target." + }, + "examples": { + "body": { + "namespace": "my-namespace", + "subject": "user-123", + "duration": 3600, + "grants": [ + { + "resource": "actor_gateway", + "target": { + "id": "00000000-0000-0000-0000-000000000000" + }, + "operations": [ + "read" + ] + } + ] + } + } + }, + { + "spec": "engine", + "method": "get", + "path": "/auth/tokens/inspect", + "slug": "inspect", + "title": "Inspect Token", + "description": "Return the namespace, grants, and expiry of the token used to authenticate the request.", + "typescript": "examples/docs/api/tokens-inspect.ts" + } + ] + }, + { + "title": "Namespaces", + "dir": "namespaces", + "endpoints": [ + { + "spec": "engine", + "method": "get", + "path": "/namespaces", + "slug": "list", + "title": "List Namespaces", + "description": "List namespaces, optionally filtered by name or ID. Results are paginated.", + "notes": "Use `namespace_id` for multiple IDs. `namespace_ids` is deprecated.", + "typescript": "examples/docs/api/namespaces-list.ts", + "parameters": { + "name": "Only return namespaces with this name.", + "namespace_ids": "Deprecated. Use `namespace_id` instead.", + "namespace_id": "Only return namespaces with these IDs. Repeat the parameter for multiple IDs." + }, + "responses": { + "200": "Matching namespaces and a cursor for the next page." + } + }, + { + "spec": "engine", + "method": "post", + "path": "/namespaces", + "slug": "create", + "title": "Create Namespace", + "description": "Create a namespace with a unique name and a display name.", + "typescript": "examples/docs/api/namespaces-create.ts", + "parameters": { + "name": "Unique name used to identify the namespace.", + "display_name": "Human-readable name for the namespace." + }, + "examples": { + "body": { + "name": "my-app", + "display_name": "My App" + } + }, + "responses": { + "200": "The newly created namespace." + } + } + ] + }, + { + "title": "Pools", + "dir": "pools", + "endpoints": [ + { + "spec": "engine", + "method": "get", + "path": "/pools", + "slug": "list", + "title": "List Pools", + "description": "List the node pools configured in a namespace, ordered by name. Results are paginated.", + "typescript": "examples/docs/api/pools-list.ts", + "examples": { + "query": { + "namespace": "$RIVET_NAMESPACE" + } + }, + "responses": { + "200": "A page of node pools." + } + }, + { + "spec": "engine", + "method": "get", + "path": "/pools/{pool}", + "slug": "get", + "title": "Get Pool", + "description": "Get a node pool's configuration.", + "typescript": "examples/docs/api/pools-get.ts", + "examples": { + "path": { + "pool": "$RIVET_POOL" + }, + "query": { + "namespace": "$RIVET_NAMESPACE" + } + }, + "responses": { + "200": "The node pool." + } + }, + { + "spec": "engine", + "method": "put", + "path": "/pools/{pool}", + "slug": "upsert", + "title": "Upsert Pool", + "description": "Create or replace a node pool's configuration.", + "notes": "Omitted fields take their defaults. Unknown fields are rejected.", + "typescript": "examples/docs/api/pools-upsert.ts", + "examples": { + "path": { + "pool": "$RIVET_POOL" + }, + "query": { + "namespace": "$RIVET_NAMESPACE" + }, + "body": { + "drain_on_version_upgrade": true + } + }, + "responses": { + "200": "The stored node pool." + } + }, + { + "spec": "engine", + "method": "delete", + "path": "/pools/{pool}", + "slug": "delete", + "title": "Delete Pool", + "description": "Delete a node pool.", + "notes": "Fails with `pool.nodes_connected` while any node of the pool is connected.", + "typescript": "examples/docs/api/pools-delete.ts", + "examples": { + "path": { + "pool": "$RIVET_POOL" + }, + "query": { + "namespace": "$RIVET_NAMESPACE" + } + }, + "responses": { + "200": "The node pool was deleted." + } + }, + { + "spec": "engine", + "method": "get", + "path": "/pools/{pool}/nodes", + "slug": "list-nodes", + "title": "List Pool Nodes", + "description": "List the live nodes of a node pool in node key order. Results are paginated.", + "typescript": "examples/docs/api/pools-list-nodes.ts", + "examples": { + "path": { + "pool": "$RIVET_POOL" + }, + "query": { + "namespace": "$RIVET_NAMESPACE" + } + }, + "responses": { + "200": "A page of live nodes." + } + } + ], + "pages": [ + { + "title": "Worker Connection", + "href": "/docs/api/worker-connect", + "badge": "WS", + "after": "list-nodes" + } + ] + }, + { + "title": "Control Plane", + "dir": "control-plane", + "endpoints": [ + { + "spec": "engine", + "method": "get", + "path": "/metadata", + "slug": "metadata", + "title": "Get Metadata", + "description": "Get build, runtime, compiler, and fleet protocol metadata for the control plane.", + "notes": "The protocol versions are the versions agreed on by the fleet, which can differ from the versions compiled into the responding node.", + "typescript": "examples/docs/api/control-plane-metadata.ts", + "auth": "none", + "responses": { + "200": "Build and protocol metadata for the responding node and its fleet." + } + }, + { + "spec": "engine", + "method": "get", + "path": "/datacenters", + "slug": "datacenters", + "title": "List Datacenters", + "description": "List the datacenters configured for the control plane.", + "typescript": "examples/docs/api/control-plane-datacenters.ts", + "responses": { + "200": "Configured datacenters and an empty pagination cursor." + } + } + ] + } + ] } diff --git a/vendor/api/docs/error-registry.json b/vendor/api/docs/error-registry.json index 01f74932..d79c7c9a 100644 --- a/vendor/api/docs/error-registry.json +++ b/vendor/api/docs/error-registry.json @@ -42,14 +42,7 @@ { "code": "duplicate_key", "message": "Actor key already in use.", - "statuses": [ - { - "status": 409, - "surfaces": [ - "control plane" - ] - } - ] + "statuses": [] }, { "code": "input_too_large", @@ -99,14 +92,12 @@ { "code": "invalid_request", "message": "Invalid hibernatable websocket connection ID", - "statuses": [ - { - "status": 400, - "surfaces": [ - "gateway" - ] - } - ] + "statuses": [] + }, + { + "code": "invalid_version", + "message": "The requested actor version cannot be created here.", + "statuses": [] }, { "code": "js_callback_unavailable", @@ -150,6 +141,16 @@ } ] }, + { + "code": "migrate_from_v2_unsupported", + "message": "The cluster cannot hold actors for a V2 migration yet.", + "statuses": [] + }, + { + "code": "migrating_from_v2", + "message": "The actor is moving to this cluster from V2. Retry after the hinted delay.", + "statuses": [] + }, { "code": "missing_input", "message": "Actor input is missing.", @@ -167,7 +168,6 @@ { "status": 404, "surfaces": [ - "control plane", "gateway" ] } @@ -221,6 +221,7 @@ { "status": 403, "surfaces": [ + "control plane", "gateway" ] } @@ -238,6 +239,7 @@ { "status": 404, "surfaces": [ + "control plane", "gateway" ] } @@ -250,6 +252,7 @@ { "status": 401, "surfaces": [ + "control plane", "gateway" ] } @@ -291,12 +294,6 @@ "code": "issuance_disabled", "message": "JWT issuance is not enabled for this deployment.", "statuses": [ - { - "status": 403, - "surfaces": [ - "control plane" - ] - }, { "status": 503, "surfaces": [ @@ -607,7 +604,7 @@ }, { "name": "envoy", - "description": "Node connections, and validation of namespace and pool names.", + "description": null, "errors": [ { "code": "connect_overloaded", @@ -691,6 +688,18 @@ } ] }, + { + "code": "request_timeout", + "message": "Timed out waiting for the actor to become ready.", + "statuses": [ + { + "status": 504, + "surfaces": [ + "gateway" + ] + } + ] + }, { "code": "service_unavailable", "message": "Service unavailable.", @@ -721,6 +730,11 @@ } ] }, + { + "name": "kv", + "description": "Low-level KV storage inside an actor.", + "errors": [] + }, { "name": "message", "description": "Message size limits on connections.", @@ -763,26 +777,12 @@ { "code": "name_not_unique", "message": "A namespace with this name already exists.", - "statuses": [ - { - "status": 409, - "surfaces": [ - "control plane" - ] - } - ] + "statuses": [] }, { "code": "not_found", "message": "The namespace does not exist.", - "statuses": [ - { - "status": 404, - "surfaces": [ - "control plane" - ] - } - ] + "statuses": [] } ] }, @@ -804,7 +804,7 @@ }, { "name": "pool", - "description": "Node pool configuration.", + "description": null, "errors": [ { "code": "invalid", @@ -814,26 +814,12 @@ { "code": "nodes_connected", "message": "The node pool still has connected nodes.", - "statuses": [ - { - "status": 409, - "surfaces": [ - "control plane" - ] - } - ] + "statuses": [] }, { "code": "not_found", "message": "The node pool does not exist.", - "statuses": [ - { - "status": 404, - "surfaces": [ - "control plane" - ] - } - ] + "statuses": [] }, { "code": "serverless_unsupported", diff --git a/vendor/api/docs/sidebar.json b/vendor/api/docs/sidebar.json index 2fd79095..85746204 100644 --- a/vendor/api/docs/sidebar.json +++ b/vendor/api/docs/sidebar.json @@ -43,11 +43,6 @@ "href": "/docs/api/actors/list", "badge": "GET" }, - { - "title": "Get Actor", - "href": "/docs/api/actors/get", - "badge": "GET" - }, { "title": "Create Actor", "href": "/docs/api/actors/create", @@ -93,16 +88,6 @@ "href": "/docs/api/gateway/queue", "badge": "POST" }, - { - "title": "Raw HTTP Request", - "href": "/docs/api/gateway/request", - "badge": "ANY" - }, - { - "title": "Raw WebSocket", - "href": "/docs/api/websockets", - "badge": "WS" - }, { "title": "Connect", "href": "/docs/api/gateway/connect", @@ -119,91 +104,9 @@ "badge": "GET" }, { - "title": "Inspector", - "icon": "faMagnifyingGlass", - "pages": [ - { - "title": "Get Summary", - "href": "/docs/api/inspector/summary", - "badge": "GET" - }, - { - "title": "Get State", - "href": "/docs/api/inspector/state-get", - "badge": "GET" - }, - { - "title": "Patch State", - "href": "/docs/api/inspector/state-patch", - "badge": "PATCH" - }, - { - "title": "List Connections", - "href": "/docs/api/inspector/connections", - "badge": "GET" - }, - { - "title": "List Actions", - "href": "/docs/api/inspector/rpcs", - "badge": "GET" - }, - { - "title": "Invoke Action", - "href": "/docs/api/inspector/action", - "badge": "POST" - }, - { - "title": "Get Queue", - "href": "/docs/api/inspector/queue-get", - "badge": "GET" - }, - { - "title": "Enqueue Message", - "href": "/docs/api/inspector/queue-post", - "badge": "POST" - }, - { - "title": "Clear Queue", - "href": "/docs/api/inspector/queue-delete", - "badge": "DELETE" - }, - { - "title": "Get Traces", - "href": "/docs/api/inspector/traces", - "badge": "GET" - }, - { - "title": "Get Workflow History", - "href": "/docs/api/inspector/workflow-history", - "badge": "GET" - }, - { - "title": "Replay Workflow", - "href": "/docs/api/inspector/workflow-replay", - "badge": "POST" - }, - { - "title": "Get Database Schema", - "href": "/docs/api/inspector/database-schema", - "badge": "GET" - }, - { - "title": "Query Database Rows", - "href": "/docs/api/inspector/database-rows", - "badge": "GET" - }, - { - "title": "Execute SQL", - "href": "/docs/api/inspector/database-execute", - "badge": "POST" - }, - { - "title": "Inspector Connect", - "href": "/docs/api/inspector-connect", - "badge": "WS" - } - ], - "collapsible": true + "title": "Raw WebSocket", + "href": "/docs/api/websockets", + "badge": "WS" } ] }, @@ -238,35 +141,35 @@ ] }, { - "title": "Node Pools", + "title": "Pools", "pages": [ { - "title": "List Node Pools", + "title": "List Pools", "href": "/docs/api/pools/list", "badge": "GET" }, { - "title": "Get Node Pool", + "title": "Get Pool", "href": "/docs/api/pools/get", "badge": "GET" }, { - "title": "Upsert Node Pool", + "title": "Upsert Pool", "href": "/docs/api/pools/upsert", "badge": "PUT" }, { - "title": "Delete Node Pool", + "title": "Delete Pool", "href": "/docs/api/pools/delete", "badge": "DELETE" }, { - "title": "List Nodes", + "title": "List Pool Nodes", "href": "/docs/api/pools/list-nodes", "badge": "GET" }, { - "title": "Node Connection", + "title": "Worker Connection", "href": "/docs/api/worker-connect", "badge": "WS" } diff --git a/vendor/api/engine/artifacts/openapi.json b/vendor/api/engine/artifacts/openapi.json index eab3912a..e8e69f35 100644 --- a/vendor/api/engine/artifacts/openapi.json +++ b/vendor/api/engine/artifacts/openapi.json @@ -8,10 +8,10 @@ "email": "developer@rivet.dev" }, "license": { - "name": "LicenseRef-RivetEnterprise", - "identifier": "LicenseRef-RivetEnterprise" + "name": "Apache-2.0", + "identifier": "Apache-2.0" }, - "version": "2.3.20" + "version": "2.3.31" }, "servers": [ { @@ -93,7 +93,7 @@ } }, "400": { - "description": "`validation.invalid_input`: the subject exceeds 256 UTF-8 bytes, the duration is outside the allowed range, or the grant set is invalid (empty, more than 32 grants, a grant without operations or with more than 5, or a `token`, `acl` or `jwt` resource). `envoy.invalid_namespace_name`: the `namespace` value is not a DNS label of 1 to 63 lowercase letters, digits and hyphens.", + "description": "`validation.invalid_input`: the subject exceeds 256 UTF-8 bytes, the duration is outside the allowed range, or the grant set is invalid (empty, more than 32 grants, a grant without operations or with more than 5, or a `token` or `jwt` resource). `envoy.invalid_namespace_name`: the `namespace` value is not a DNS label of 1 to 63 lowercase letters, digits and hyphens.", "content": { "application/json": { "schema": { @@ -1685,7 +1685,7 @@ } }, "400": { - "description": "`actor.invalid_name`: `name` is empty or longer than 64 bytes. `actor.invalid_key`: `key` is longer than 1024 bytes. `actor.invalid_key_encoding`: `key` is not in canonical slash-separated form. `actor.key_owned_elsewhere`: another datacenter owns the key. `envoy.invalid_pool_name`: `runner_name_selector` is not a valid pool name. `envoy.invalid_namespace_name`: the `namespace` value is not a DNS label of 1 to 63 lowercase letters, digits and hyphens.", + "description": "`actor.invalid_name`: `name` is empty or longer than 64 bytes. `actor.invalid_key`: `key` is longer than 1024 bytes. `actor.invalid_key_encoding`: `key` is not in canonical slash-separated form. `actor.key_owned_elsewhere`: another datacenter owns the key. `envoy.invalid_pool_name`: `pool` is not a valid pool name. `envoy.invalid_namespace_name`: the `namespace` value is not a DNS label of 1 to 63 lowercase letters, digits and hyphens.", "content": { "application/json": { "schema": { @@ -1861,7 +1861,7 @@ } }, "400": { - "description": "`actor.invalid_name`: `name` is empty or longer than 64 bytes. `actor.invalid_key`: `key` is longer than 1024 bytes. `actor.invalid_key_encoding`: `key` is not in canonical slash-separated form. `actor.key_owned_elsewhere`: another datacenter owns the key. `envoy.invalid_pool_name`: `runner_name_selector` is not a valid pool name. `envoy.invalid_namespace_name`: the `namespace` value is not a DNS label of 1 to 63 lowercase letters, digits and hyphens.", + "description": "`actor.invalid_name`: `name` is empty or longer than 64 bytes. `actor.invalid_key`: `key` is longer than 1024 bytes. `actor.invalid_key_encoding`: `key` is not in canonical slash-separated form. `actor.key_owned_elsewhere`: another datacenter owns the key. `envoy.invalid_pool_name`: `pool` is not a valid pool name. `envoy.invalid_namespace_name`: the `namespace` value is not a DNS label of 1 to 63 lowercase letters, digits and hyphens.", "content": { "application/json": { "schema": { @@ -2690,7 +2690,7 @@ "name", "key", "namespace", - "runner_name_selector", + "pool", "create_ts", "start_ts", "pending_allocation_ts", @@ -2715,7 +2715,7 @@ "type": "string", "description": "Name of the namespace the actor belongs to." }, - "runner_name_selector": { + "pool": { "type": "string", "description": "Name of the node pool the actor runs in." }, @@ -2817,7 +2817,7 @@ ], "description": "Actor input as standard base64 (with padding)." }, - "runner_name_selector": { + "pool": { "type": [ "string", "null" @@ -2877,7 +2877,7 @@ ], "description": "Actor input as standard base64 (with padding)." }, - "runner_name_selector": { + "pool": { "type": [ "string", "null" @@ -3308,6 +3308,7 @@ "pool", "namespace", "datacenter", + "version", "create_ts", "last_ping_ts", "connected", @@ -3332,6 +3333,12 @@ "description": "Datacenter name.", "example": "default" }, + "version": { + "type": "integer", + "format": "int64", + "description": "Version the node announced when it connected. New actors are placed only on nodes at the newest version with a connected node in the pool.", + "example": 3 + }, "create_ts": { "type": "integer", "format": "int64", diff --git a/vendor/api/examples/docs/actors-quickstart-next-js/registry.ts b/vendor/api/examples/docs/actors-quickstart-next-js/registry.ts deleted file mode 100644 index 4afe732a..00000000 --- a/vendor/api/examples/docs/actors-quickstart-next-js/registry.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { actor, setup } from "rivetkit"; - -export const counter = actor({ - state: { count: 0 }, - actions: { - increment: (c, x: number) => { - c.state.count += x; - c.broadcast("newCount", c.state.count); - return c.state.count; - }, - }, -}); - -export const registry = setup({ - use: { counter }, -}); diff --git a/vendor/api/examples/docs/actors-quickstart-react/index.ts b/vendor/api/examples/docs/actors-quickstart-react/backend/index.ts similarity index 100% rename from vendor/api/examples/docs/actors-quickstart-react/index.ts rename to vendor/api/examples/docs/actors-quickstart-react/backend/index.ts diff --git a/vendor/api/examples/docs/actors-quickstart-react/Counter.tsx b/vendor/api/examples/docs/actors-quickstart-react/frontend/Counter.tsx similarity index 85% rename from vendor/api/examples/docs/actors-quickstart-react/Counter.tsx rename to vendor/api/examples/docs/actors-quickstart-react/frontend/Counter.tsx index a62ee024..26aa5be7 100644 --- a/vendor/api/examples/docs/actors-quickstart-react/Counter.tsx +++ b/vendor/api/examples/docs/actors-quickstart-react/frontend/Counter.tsx @@ -1,16 +1,16 @@ import { createRivetKit } from "@rivetkit/react"; import { useState } from "react"; -import type { registry } from "./index"; +import type { registry } from "../backend/index"; const { useActor } = createRivetKit("http://localhost:6420"); -function Counter() { +export function Counter() { const [count, setCount] = useState(0); // Get or create a counter actor for the key "my-counter" const counter = useActor({ name: "counter", - key: ["my-counter"] + key: ["my-counter"], }); // Listen to realtime events diff --git a/vendor/api/examples/docs/actors-quickstart-react/frontend/main.tsx b/vendor/api/examples/docs/actors-quickstart-react/frontend/main.tsx new file mode 100644 index 00000000..a8e4ea9d --- /dev/null +++ b/vendor/api/examples/docs/actors-quickstart-react/frontend/main.tsx @@ -0,0 +1,9 @@ +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import { Counter } from "./Counter"; + +createRoot(document.getElementById("root")!).render( + + + , +); diff --git a/vendor/api/examples/docs/actors-versions/programmatic-version.ts b/vendor/api/examples/docs/actors-versions/programmatic-version.ts deleted file mode 100644 index 9763d971..00000000 --- a/vendor/api/examples/docs/actors-versions/programmatic-version.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { actor, setup } from "rivetkit"; - -const myActor = actor({ state: {}, actions: {} }); - -const registry = setup({ - use: { myActor }, - envoy: { - version: 2, - }, -}); diff --git a/vendor/api/examples/docs/api/actors-destroy.ts b/vendor/api/examples/docs/api/actors-destroy.ts index 7718ad8c..d76fa102 100644 --- a/vendor/api/examples/docs/api/actors-destroy.ts +++ b/vendor/api/examples/docs/api/actors-destroy.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; const actorId = "00000000-0000-0000-0000-000000000000"; diff --git a/vendor/api/examples/docs/api/actors-list-names.ts b/vendor/api/examples/docs/api/actors-list-names.ts index ce5f865f..19ca05e2 100644 --- a/vendor/api/examples/docs/api/actors-list-names.ts +++ b/vendor/api/examples/docs/api/actors-list-names.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; diff --git a/vendor/api/examples/docs/api/actors-list.ts b/vendor/api/examples/docs/api/actors-list.ts index fcca97ee..55a79fcb 100644 --- a/vendor/api/examples/docs/api/actors-list.ts +++ b/vendor/api/examples/docs/api/actors-list.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; diff --git a/vendor/api/examples/docs/api/actors-reschedule.ts b/vendor/api/examples/docs/api/actors-reschedule.ts index 3a2f9b23..3bb1a563 100644 --- a/vendor/api/examples/docs/api/actors-reschedule.ts +++ b/vendor/api/examples/docs/api/actors-reschedule.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; const actorId = "00000000-0000-0000-0000-000000000000"; diff --git a/vendor/api/examples/docs/api/actors-sleep.ts b/vendor/api/examples/docs/api/actors-sleep.ts index e1232b21..a1d07784 100644 --- a/vendor/api/examples/docs/api/actors-sleep.ts +++ b/vendor/api/examples/docs/api/actors-sleep.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; const actorId = "00000000-0000-0000-0000-000000000000"; diff --git a/vendor/api/examples/docs/api/connection-actions.ts b/vendor/api/examples/docs/api/connection-actions.ts index d90ec127..3de81cd1 100644 --- a/vendor/api/examples/docs/api/connection-actions.ts +++ b/vendor/api/examples/docs/api/connection-actions.ts @@ -1,5 +1,5 @@ const ws = new WebSocket( - `wss://rivet.example.com/gateway/${process.env.ACTOR_ID}/connect`, + `wss://api.rivet.dev/gateway/${process.env.ACTOR_ID}/connect`, ["rivet", "rivet_encoding.json", `rivet_token.${process.env.RIVET_TOKEN}`], ); diff --git a/vendor/api/examples/docs/api/connection-connect.ts b/vendor/api/examples/docs/api/connection-connect.ts index ee4bf891..88e74ed3 100644 --- a/vendor/api/examples/docs/api/connection-connect.ts +++ b/vendor/api/examples/docs/api/connection-connect.ts @@ -1,7 +1,7 @@ // Open a connection by actor name. The selector query parameters are the same // ones used by the HTTP endpoints; the token and encoding travel as // WebSocket subprotocols because browsers cannot set headers on an upgrade. -const url = new URL("wss://rivet.example.com/gateway/counter/connect"); +const url = new URL("wss://api.rivet.dev/gateway/counter/connect"); url.searchParams.set("rvt-namespace", process.env.RIVET_NAMESPACE!); url.searchParams.set("rvt-method", "getOrCreate"); url.searchParams.set("rvt-key", "my-counter"); diff --git a/vendor/api/examples/docs/api/connection-errors.ts b/vendor/api/examples/docs/api/connection-errors.ts index f8e796c7..6345825a 100644 --- a/vendor/api/examples/docs/api/connection-errors.ts +++ b/vendor/api/examples/docs/api/connection-errors.ts @@ -1,5 +1,5 @@ const ws = new WebSocket( - `wss://rivet.example.com/gateway/${process.env.ACTOR_ID}/connect`, + `wss://api.rivet.dev/gateway/${process.env.ACTOR_ID}/connect`, ["rivet", "rivet_encoding.json", `rivet_token.${process.env.RIVET_TOKEN}`], ); diff --git a/vendor/api/examples/docs/api/connection-events.ts b/vendor/api/examples/docs/api/connection-events.ts index 71ad178a..7e85c61b 100644 --- a/vendor/api/examples/docs/api/connection-events.ts +++ b/vendor/api/examples/docs/api/connection-events.ts @@ -1,5 +1,5 @@ const ws = new WebSocket( - `wss://rivet.example.com/gateway/${process.env.ACTOR_ID}/connect`, + `wss://api.rivet.dev/gateway/${process.env.ACTOR_ID}/connect`, ["rivet", "rivet_encoding.json", `rivet_token.${process.env.RIVET_TOKEN}`], ); diff --git a/vendor/api/examples/docs/api/control-plane-datacenters.ts b/vendor/api/examples/docs/api/control-plane-datacenters.ts index 6f14c5eb..d5afca6c 100644 --- a/vendor/api/examples/docs/api/control-plane-datacenters.ts +++ b/vendor/api/examples/docs/api/control-plane-datacenters.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const token = process.env.RIVET_TOKEN ?? ""; const response = await fetch(`${endpoint}/datacenters`, { diff --git a/vendor/api/examples/docs/api/control-plane-metadata.ts b/vendor/api/examples/docs/api/control-plane-metadata.ts index ea784880..43300b91 100644 --- a/vendor/api/examples/docs/api/control-plane-metadata.ts +++ b/vendor/api/examples/docs/api/control-plane-metadata.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const response = await fetch(`${endpoint}/metadata`); const metadata = await response.json(); diff --git a/vendor/api/examples/docs/api/gateway-metadata.ts b/vendor/api/examples/docs/api/gateway-metadata.ts index 95da90f4..d677d2dd 100644 --- a/vendor/api/examples/docs/api/gateway-metadata.ts +++ b/vendor/api/examples/docs/api/gateway-metadata.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const response = await fetch( `${endpoint}/gateway/${process.env.ACTOR_ID}/metadata`, { diff --git a/vendor/api/examples/docs/api/gateway-queue.ts b/vendor/api/examples/docs/api/gateway-queue.ts index 73f95114..8d6a2aa6 100644 --- a/vendor/api/examples/docs/api/gateway-queue.ts +++ b/vendor/api/examples/docs/api/gateway-queue.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const actorId = process.env.ACTOR_ID; const response = await fetch(`${endpoint}/gateway/${actorId}/queue/increment`, { method: "POST", diff --git a/vendor/api/examples/docs/api/inspector-action.ts b/vendor/api/examples/docs/api/inspector-action.ts deleted file mode 100644 index ac8aca2c..00000000 --- a/vendor/api/examples/docs/api/inspector-action.ts +++ /dev/null @@ -1,14 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/action/increment`, - { - method: "POST", - headers: { - Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ args: [1] }), - }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/api/examples/docs/api/inspector-connections.ts b/vendor/api/examples/docs/api/inspector-connections.ts deleted file mode 100644 index cebb890d..00000000 --- a/vendor/api/examples/docs/api/inspector-connections.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/connections`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/api/examples/docs/api/inspector-database-execute.ts b/vendor/api/examples/docs/api/inspector-database-execute.ts deleted file mode 100644 index 0786a92e..00000000 --- a/vendor/api/examples/docs/api/inspector-database-execute.ts +++ /dev/null @@ -1,17 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/database/execute`, - { - method: "POST", - headers: { - Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ - sql: "SELECT * FROM users WHERE id = ?", - args: ["user-123"], - }), - }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/api/examples/docs/api/inspector-database-rows.ts b/vendor/api/examples/docs/api/inspector-database-rows.ts deleted file mode 100644 index a21e1be3..00000000 --- a/vendor/api/examples/docs/api/inspector-database-rows.ts +++ /dev/null @@ -1,12 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const query = new URLSearchParams({ - table: "users", - limit: "100", - offset: "0", -}); -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/database/rows?${query}`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/api/examples/docs/api/inspector-database-schema.ts b/vendor/api/examples/docs/api/inspector-database-schema.ts deleted file mode 100644 index e6d5acdc..00000000 --- a/vendor/api/examples/docs/api/inspector-database-schema.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/database/schema`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/api/examples/docs/api/inspector-queue-delete.ts b/vendor/api/examples/docs/api/inspector-queue-delete.ts deleted file mode 100644 index 748c1b4c..00000000 --- a/vendor/api/examples/docs/api/inspector-queue-delete.ts +++ /dev/null @@ -1,10 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/queue`, - { - method: "DELETE", - headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` }, - }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/api/examples/docs/api/inspector-queue-get.ts b/vendor/api/examples/docs/api/inspector-queue-get.ts deleted file mode 100644 index a55ec407..00000000 --- a/vendor/api/examples/docs/api/inspector-queue-get.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/queue?limit=50`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/api/examples/docs/api/inspector-queue-post.ts b/vendor/api/examples/docs/api/inspector-queue-post.ts deleted file mode 100644 index d5c71989..00000000 --- a/vendor/api/examples/docs/api/inspector-queue-post.ts +++ /dev/null @@ -1,14 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/queue`, - { - method: "POST", - headers: { - Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ name: "increment", body: { amount: 1 } }), - }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/api/examples/docs/api/inspector-rpcs.ts b/vendor/api/examples/docs/api/inspector-rpcs.ts deleted file mode 100644 index 356e615e..00000000 --- a/vendor/api/examples/docs/api/inspector-rpcs.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/rpcs`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/api/examples/docs/api/inspector-state-get.ts b/vendor/api/examples/docs/api/inspector-state-get.ts deleted file mode 100644 index 783deb57..00000000 --- a/vendor/api/examples/docs/api/inspector-state-get.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/state`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/api/examples/docs/api/inspector-state-patch.ts b/vendor/api/examples/docs/api/inspector-state-patch.ts deleted file mode 100644 index 36ef34dc..00000000 --- a/vendor/api/examples/docs/api/inspector-state-patch.ts +++ /dev/null @@ -1,14 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/state`, - { - method: "PATCH", - headers: { - Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ state: { count: 2 } }), - }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/api/examples/docs/api/inspector-summary.ts b/vendor/api/examples/docs/api/inspector-summary.ts deleted file mode 100644 index 37f0f793..00000000 --- a/vendor/api/examples/docs/api/inspector-summary.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/summary`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/api/examples/docs/api/inspector-traces.ts b/vendor/api/examples/docs/api/inspector-traces.ts deleted file mode 100644 index 9a3c1a62..00000000 --- a/vendor/api/examples/docs/api/inspector-traces.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/traces?startMs=0&limit=100`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/api/examples/docs/api/inspector-workflow-history.ts b/vendor/api/examples/docs/api/inspector-workflow-history.ts deleted file mode 100644 index 64d289d0..00000000 --- a/vendor/api/examples/docs/api/inspector-workflow-history.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/workflow-history`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/api/examples/docs/api/inspector-workflow-replay.ts b/vendor/api/examples/docs/api/inspector-workflow-replay.ts deleted file mode 100644 index 3bf3cdc8..00000000 --- a/vendor/api/examples/docs/api/inspector-workflow-replay.ts +++ /dev/null @@ -1,14 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/workflow/replay`, - { - method: "POST", - headers: { - Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ entryId: "entry-123" }), - }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/api/examples/docs/api/namespaces-create.ts b/vendor/api/examples/docs/api/namespaces-create.ts index c2f92ff5..3bda46bc 100644 --- a/vendor/api/examples/docs/api/namespaces-create.ts +++ b/vendor/api/examples/docs/api/namespaces-create.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const token = process.env.RIVET_TOKEN ?? ""; const response = await fetch(`${endpoint}/namespaces`, { diff --git a/vendor/api/examples/docs/api/namespaces-list.ts b/vendor/api/examples/docs/api/namespaces-list.ts index 5b598685..34700884 100644 --- a/vendor/api/examples/docs/api/namespaces-list.ts +++ b/vendor/api/examples/docs/api/namespaces-list.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const token = process.env.RIVET_TOKEN ?? ""; const response = await fetch(`${endpoint}/namespaces`, { diff --git a/vendor/api/examples/docs/api/pools-delete.ts b/vendor/api/examples/docs/api/pools-delete.ts new file mode 100644 index 00000000..ad9c5134 --- /dev/null +++ b/vendor/api/examples/docs/api/pools-delete.ts @@ -0,0 +1,16 @@ +const endpoint = "https://api.rivet.dev"; +const namespace = process.env.RIVET_NAMESPACE ?? "default"; +const token = process.env.RIVET_TOKEN ?? ""; +const pool = process.env.RIVET_POOL ?? "default"; + +const params = new URLSearchParams({ namespace }); +const response = await fetch( + `${endpoint}/pools/${encodeURIComponent(pool)}?${params}`, + { + method: "DELETE", + headers: { Authorization: `Bearer ${token}` }, + }, +); +console.log(response.status); + +export {}; diff --git a/vendor/api/examples/docs/api/pools-get.ts b/vendor/api/examples/docs/api/pools-get.ts new file mode 100644 index 00000000..852a5f71 --- /dev/null +++ b/vendor/api/examples/docs/api/pools-get.ts @@ -0,0 +1,13 @@ +const endpoint = "https://api.rivet.dev"; +const namespace = process.env.RIVET_NAMESPACE ?? "default"; +const token = process.env.RIVET_TOKEN ?? ""; +const pool = process.env.RIVET_POOL ?? "default"; + +const params = new URLSearchParams({ namespace }); +const response = await fetch( + `${endpoint}/pools/${encodeURIComponent(pool)}?${params}`, + { headers: { Authorization: `Bearer ${token}` } }, +); +console.log(await response.json()); + +export {}; diff --git a/vendor/api/examples/docs/api/pools-list-nodes.ts b/vendor/api/examples/docs/api/pools-list-nodes.ts new file mode 100644 index 00000000..b55c107f --- /dev/null +++ b/vendor/api/examples/docs/api/pools-list-nodes.ts @@ -0,0 +1,14 @@ +const endpoint = "https://api.rivet.dev"; +const namespace = process.env.RIVET_NAMESPACE ?? "default"; +const token = process.env.RIVET_TOKEN ?? ""; +const pool = process.env.RIVET_POOL ?? "default"; + +const params = new URLSearchParams({ namespace }); +const response = await fetch( + `${endpoint}/pools/${encodeURIComponent(pool)}/nodes?${params}`, + { headers: { Authorization: `Bearer ${token}` } }, +); +const { nodes, pagination } = await response.json(); +console.log(nodes, pagination.cursor); + +export {}; diff --git a/vendor/api/examples/docs/api/workers-configs-list.ts b/vendor/api/examples/docs/api/pools-list.ts similarity index 52% rename from vendor/api/examples/docs/api/workers-configs-list.ts rename to vendor/api/examples/docs/api/pools-list.ts index 1f1c8521..eac08588 100644 --- a/vendor/api/examples/docs/api/workers-configs-list.ts +++ b/vendor/api/examples/docs/api/pools-list.ts @@ -1,12 +1,12 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; const params = new URLSearchParams({ namespace }); -const response = await fetch(`${endpoint}/runner-configs?${params}`, { +const response = await fetch(`${endpoint}/pools?${params}`, { headers: { Authorization: `Bearer ${token}` }, }); -const { runner_configs } = await response.json(); -console.log(runner_configs); +const { pools, pagination } = await response.json(); +console.log(pools, pagination.cursor); export {}; diff --git a/vendor/api/examples/docs/api/workers-configs-upsert.ts b/vendor/api/examples/docs/api/pools-upsert.ts similarity index 59% rename from vendor/api/examples/docs/api/workers-configs-upsert.ts rename to vendor/api/examples/docs/api/pools-upsert.ts index 50a37d3d..0097c1c7 100644 --- a/vendor/api/examples/docs/api/workers-configs-upsert.ts +++ b/vendor/api/examples/docs/api/pools-upsert.ts @@ -1,18 +1,18 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; -const workerName = process.env.RUNNER_NAME ?? "default"; +const pool = process.env.RIVET_POOL ?? "default"; const params = new URLSearchParams({ namespace }); const response = await fetch( - `${endpoint}/runner-configs/${encodeURIComponent(workerName)}?${params}`, + `${endpoint}/pools/${encodeURIComponent(pool)}?${params}`, { method: "PUT", headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", }, - body: JSON.stringify({ datacenters: { local: { normal: {} } } }), + body: JSON.stringify({ drain_on_version_upgrade: true }), }, ); console.log(await response.json()); diff --git a/vendor/api/examples/docs/api/tokens-inspect.ts b/vendor/api/examples/docs/api/tokens-inspect.ts index c562d121..7573b89f 100644 --- a/vendor/api/examples/docs/api/tokens-inspect.ts +++ b/vendor/api/examples/docs/api/tokens-inspect.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const token = process.env.RIVET_TOKEN ?? ""; // Inspect reports on the token used to authenticate the request itself. diff --git a/vendor/api/examples/docs/api/workers-configs-delete.ts b/vendor/api/examples/docs/api/workers-configs-delete.ts deleted file mode 100644 index cdc01d9e..00000000 --- a/vendor/api/examples/docs/api/workers-configs-delete.ts +++ /dev/null @@ -1,13 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const namespace = process.env.RIVET_NAMESPACE ?? "default"; -const token = process.env.RIVET_TOKEN ?? ""; -const workerName = process.env.RUNNER_NAME ?? "default"; - -const params = new URLSearchParams({ namespace }); -const response = await fetch( - `${endpoint}/runner-configs/${encodeURIComponent(workerName)}?${params}`, - { method: "DELETE", headers: { Authorization: `Bearer ${token}` } }, -); -console.log(response.ok); - -export {}; diff --git a/vendor/api/examples/docs/api/workers-configs-refresh-metadata.ts b/vendor/api/examples/docs/api/workers-configs-refresh-metadata.ts index 337d7c97..1f1a7c02 100644 --- a/vendor/api/examples/docs/api/workers-configs-refresh-metadata.ts +++ b/vendor/api/examples/docs/api/workers-configs-refresh-metadata.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; const workerName = process.env.RUNNER_NAME ?? "default"; diff --git a/vendor/api/examples/docs/api/workers-list.ts b/vendor/api/examples/docs/api/workers-list.ts deleted file mode 100644 index 06f1d56e..00000000 --- a/vendor/api/examples/docs/api/workers-list.ts +++ /dev/null @@ -1,12 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const namespace = process.env.RIVET_NAMESPACE ?? "default"; -const token = process.env.RIVET_TOKEN ?? ""; - -const params = new URLSearchParams({ namespace }); -const response = await fetch(`${endpoint}/envoys?${params}`, { - headers: { Authorization: `Bearer ${token}` }, -}); -const { envoys: workers, pagination } = await response.json(); -console.log(workers, pagination.cursor); - -export {}; diff --git a/vendor/api/examples/docs/api/workers-serverless-health-check.ts b/vendor/api/examples/docs/api/workers-serverless-health-check.ts index 860536f6..c6e0c54f 100644 --- a/vendor/api/examples/docs/api/workers-serverless-health-check.ts +++ b/vendor/api/examples/docs/api/workers-serverless-health-check.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; diff --git a/vendor/api/examples/docs/cookbook-cron-jobs/daily-report.ts b/vendor/api/examples/docs/cookbook-cron-jobs/daily-report.ts deleted file mode 100644 index c434d36c..00000000 --- a/vendor/api/examples/docs/cookbook-cron-jobs/daily-report.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { actor } from "rivetkit"; - -export const dailyReport = actor({ - state: { lastRunAt: 0 }, - onCreate: async (c) => { - await c.cron.set({ - name: "daily-report", - expression: "0 9 * * *", - action: "runReport", - }); - }, - actions: { - runReport: (c) => { - // Do the job's work, then record the run. - c.state.lastRunAt = Date.now(); - }, - }, -}); diff --git a/vendor/api/examples/docs/durable-streams/client.ts b/vendor/api/examples/docs/durable-streams/client.ts new file mode 100644 index 00000000..97fdedf0 --- /dev/null +++ b/vendor/api/examples/docs/durable-streams/client.ts @@ -0,0 +1,14 @@ +import { DurableStream } from "@durable-streams/client"; + +const stream = await DurableStream.create({ + url: "http://127.0.0.1:8642/durable-streams/v1/stream/demo", + contentType: "application/json", +}); + +await stream.append(JSON.stringify({ message: "hello" })); + +// Read from the beginning, then keep receiving new messages live +const res = await stream.stream<{ message: string }>(); +res.subscribeJson(async (batch) => { + for (const item of batch.items) console.log(item.message); +}); diff --git a/vendor/api/examples/docs/durable-streams/create.ts b/vendor/api/examples/docs/durable-streams/create.ts new file mode 100644 index 00000000..582ec8f2 --- /dev/null +++ b/vendor/api/examples/docs/durable-streams/create.ts @@ -0,0 +1,11 @@ +import { DurableStream } from "@durable-streams/client"; + +// One stream per chat session +const stream = await DurableStream.create({ + url: "http://127.0.0.1:8642/durable-streams/v1/stream/chat/session-1", + contentType: "application/json", + // Delete the stream after a day with no reads or writes + ttlSeconds: 86400, +}); + +console.log("created", stream.url); diff --git a/vendor/api/examples/docs/durable-streams/producer.ts b/vendor/api/examples/docs/durable-streams/producer.ts new file mode 100644 index 00000000..eb2f8a16 --- /dev/null +++ b/vendor/api/examples/docs/durable-streams/producer.ts @@ -0,0 +1,21 @@ +import { DurableStream, IdempotentProducer } from "@durable-streams/client"; + +const stream = new DurableStream({ + url: "http://127.0.0.1:8642/durable-streams/v1/stream/chat/session-1", + contentType: "application/json", +}); + +// Keep the producer ID the same across restarts. With autoClaim, a restarted +// agent takes over and the old one can no longer write. +const producer = new IdempotentProducer(stream, "agent-session-1", { + autoClaim: true, + onError: (error) => console.error("append failed", error), +}); + +for (const token of ["It's", " sunny", " today"]) { + producer.append(JSON.stringify({ token })); +} + +// Wait until every token is stored, then close the stream +await producer.flush(); +await producer.close(); diff --git a/vendor/api/examples/docs/durable-streams/read-history.ts b/vendor/api/examples/docs/durable-streams/read-history.ts new file mode 100644 index 00000000..457570d7 --- /dev/null +++ b/vendor/api/examples/docs/durable-streams/read-history.ts @@ -0,0 +1,10 @@ +import { stream } from "@durable-streams/client"; + +const url = "http://127.0.0.1:8642/durable-streams/v1/stream/chat/session-1"; + +// Everything written so far, then stop +const res = await stream<{ token: string }>({ url, offset: "-1", live: false }); +const messages = await res.json(); + +console.log(messages); +console.log("read from here next:", res.offset); diff --git a/vendor/api/examples/docs/durable-streams/read-live.ts b/vendor/api/examples/docs/durable-streams/read-live.ts new file mode 100644 index 00000000..362854f3 --- /dev/null +++ b/vendor/api/examples/docs/durable-streams/read-live.ts @@ -0,0 +1,14 @@ +import { stream } from "@durable-streams/client"; + +const url = "http://127.0.0.1:8642/durable-streams/v1/stream/chat/session-1"; + +// "-1" starts at the beginning. Pass a saved offset to pick up where you left off. +const savedOffset: string = "-1"; + +const res = await stream<{ token: string }>({ url, offset: savedOffset, live: "sse" }); +res.subscribeJson(async (batch) => { + for (const item of batch.items) console.log(item.token); + + // Save this to resume from the same place after a refresh + console.log("offset", batch.offset); +}); diff --git a/vendor/api/examples/docs/durable-streams/write.ts b/vendor/api/examples/docs/durable-streams/write.ts new file mode 100644 index 00000000..c68ab7ce --- /dev/null +++ b/vendor/api/examples/docs/durable-streams/write.ts @@ -0,0 +1,13 @@ +import { DurableStream } from "@durable-streams/client"; + +const stream = new DurableStream({ + url: "http://127.0.0.1:8642/durable-streams/v1/stream/chat/session-1", + contentType: "application/json", +}); + +// Each append is one message +await stream.append(JSON.stringify({ token: "It's" })); +await stream.append(JSON.stringify({ token: " sunny" })); + +// Close with a final message: readers know the reply is complete +await stream.close({ body: JSON.stringify({ token: "." }) }); diff --git a/vendor/api/examples/docs/general-edge/client.ts b/vendor/api/examples/docs/general-edge/client.ts new file mode 100644 index 00000000..fde898f5 --- /dev/null +++ b/vendor/api/examples/docs/general-edge/client.ts @@ -0,0 +1,12 @@ +import { createClient } from "rivetkit/client"; +import { actor, setup } from "rivetkit"; + +const example = actor({ state: {}, actions: {} }); +const registry = setup({ use: { example } }); + +const client = createClient("http://localhost:6420"); + +// Create actor in a specific region using getOrCreate +const actorHandle = client.example.getOrCreate(["my-actor"], { + createInRegion: "atl" +}); diff --git a/vendor/api/examples/docs/general-jwt/quickstart/client.ts b/vendor/api/examples/docs/general-jwt/quickstart/client.ts index bf78e5d5..49cbb1ed 100644 --- a/vendor/api/examples/docs/general-jwt/quickstart/client.ts +++ b/vendor/api/examples/docs/general-jwt/quickstart/client.ts @@ -14,7 +14,7 @@ async function fetchToken(): Promise<{ actorId: string; token: string }> { const { actorId } = await fetchToken(); const client = createClient({ - endpoint: "https://my-namespace@rivet.example.com", + endpoint: "https://rivet.example.com", namespace: "production", // Called whenever RivetKit needs a credential, including after one expires. diff --git a/vendor/api/examples/docs/onboarding-actors/client.ts b/vendor/api/examples/docs/onboarding-actors/client.ts new file mode 100644 index 00000000..307c6365 --- /dev/null +++ b/vendor/api/examples/docs/onboarding-actors/client.ts @@ -0,0 +1,20 @@ +import { createClient } from "rivetkit/client"; +import type { registry } from "./index"; + +// Connect to the server from index.ts. The registry type checks every call. +const client = createClient("http://localhost:6420"); + +// Get the room keyed "general", creating it on first use. +const room = client.chatRoom.getOrCreate(["general"]); + +// Open a realtime connection and print each message as it arrives. +const connection = room.connect(); +connection.on("newMessage", (message: { sender: string; text: string }) => { + console.log(`${message.sender}: ${message.text}`); +}); + +// Send a message. The Actor saves it to SQLite before broadcasting it. +await connection.sendMessage("alice", "Hello, Rivet!"); + +// The history is still there after the Actor sleeps or restarts. +console.log(await room.getHistory()); diff --git a/vendor/api/examples/docs/onboarding-actors/index.ts b/vendor/api/examples/docs/onboarding-actors/index.ts new file mode 100644 index 00000000..0cf38744 --- /dev/null +++ b/vendor/api/examples/docs/onboarding-actors/index.ts @@ -0,0 +1,43 @@ +import { actor, setup } from "rivetkit"; +import { db } from "rivetkit/db"; + +// A chat room Actor. Every room key gets its own instance with its own SQLite +// database, which survives restarts and redeploys. +export const chatRoom = actor({ + // Create the messages table the first time a room starts. + db: db({ + onMigrate: async (db) => { + await db.execute(` + CREATE TABLE IF NOT EXISTS messages ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + sender TEXT NOT NULL, + text TEXT NOT NULL + ) + `); + }, + }), + + actions: { + // Save a message, then push it to everyone connected to this room. + sendMessage: async (c, sender: string, text: string) => { + await c.db.execute( + "INSERT INTO messages (sender, text) VALUES (?, ?)", + sender, + text, + ); + + c.broadcast("newMessage", { sender, text }); + }, + + // Read the room's history, oldest first. + getHistory: async (c) => { + return (await c.db.execute( + "SELECT sender, text FROM messages ORDER BY id", + )) as { sender: string; text: string }[]; + }, + }, +}); + +// Register the Actor and start serving it on http://localhost:6420. +export const registry = setup({ use: { chatRoom } }); +registry.start(); diff --git a/vendor/api/examples/docs/package.json b/vendor/api/examples/docs/package.json index a0e98db3..3ddcea78 100644 --- a/vendor/api/examples/docs/package.json +++ b/vendor/api/examples/docs/package.json @@ -1,4 +1,5 @@ { + "license": "MIT", "name": "docs-snippets", "version": "2.0.21", "private": true, @@ -11,10 +12,7 @@ "rivetkit": "workspace:*", "@rivetkit/react": "workspace:*", "@rivetkit/engine-api-full": "workspace:*", - "@rivetkit/next-js": "workspace:*", - "@rivetkit/cloudflare-workers": "workspace:*", "@rivetkit/rivetkit-wasm": "workspace:*", - "@rivetkit/supabase": "workspace:*", "@rivetkit/effect": "workspace:*", "effect": "4.0.0", "@effect/platform-node": "4.0.0", diff --git a/vendor/api/examples/docs/tsconfig.json b/vendor/api/examples/docs/tsconfig.json index 498e3a9a..ee88fd1d 100644 --- a/vendor/api/examples/docs/tsconfig.json +++ b/vendor/api/examples/docs/tsconfig.json @@ -13,5 +13,12 @@ "jsx": "react-jsx" }, "include": ["**/*.ts", "**/*.tsx"], - "exclude": ["node_modules"] + "exclude": [ + "node_modules", + "actors-quickstart-next-js", + "general-http-server/elysia-handler.ts", + "general-http-server/hono-handler.ts", + "general-http-server/serve.ts", + "actors-actions/calling-backend.ts" + ] } diff --git a/vendor/api/rivetkit-asyncapi/asyncapi.json b/vendor/api/rivetkit-asyncapi/asyncapi.json index 32b33213..404aebbb 100644 --- a/vendor/api/rivetkit-asyncapi/asyncapi.json +++ b/vendor/api/rivetkit-asyncapi/asyncapi.json @@ -2,7 +2,7 @@ "asyncapi": "3.0.0", "info": { "title": "RivetKit WebSocket Protocol", - "version": "2.4.0", + "version": "3.0.1", "description": "WebSocket protocol for bidirectional communication between RivetKit clients and actors" }, "channels": { From f2c269f8216a09571d52bbecb3a17d358dbd4a26 Mon Sep 17 00:00:00 2001 From: "rivet-docs-sync[bot]" Date: Tue, 3 Nov 2026 23:10:17 +0000 Subject: [PATCH 2/5] docs(actors): sync from rivet-dev/rivet@7aa2b2f --- vendor/actors/docs/content/docs/actions.mdx | 19 +- .../actors/docs/content/docs/appearance.mdx | 6 +- .../docs/content/docs/authentication.mdx | 129 ++++ .../docs/content/docs/clients/javascript.mdx | 4 +- .../docs/content/docs/clients/react.mdx | 2 +- .../actors/docs/content/docs/clients/rust.mdx | 34 +- .../docs/content/docs/clients/swift.mdx | 2 +- .../docs/content/docs/clients/swiftui.mdx | 2 +- vendor/actors/docs/content/docs/debugging.mdx | 308 -------- .../content/docs/environment-variables.mdx | 6 +- vendor/actors/docs/content/docs/events.mdx | 11 - .../actors/docs/content/docs/http-server.mdx | 2 +- vendor/actors/docs/content/docs/limits.mdx | 72 +- .../content/docs/production-checklist.mdx | 2 +- vendor/actors/docs/content/docs/queues.mdx | 11 - .../docs/content/docs/quickstart/backend.mdx | 4 +- .../docs/content/docs/quickstart/effect.mdx | 4 +- .../docs/content/docs/quickstart/next-js.mdx | 65 -- .../docs/content/docs/quickstart/react.mdx | 49 +- .../docs/content/docs/quickstart/rust.mdx | 4 +- .../content/docs/registry-configuration.mdx | 2 +- .../docs/content/docs/request-handler.mdx | 2 - .../docs/content/docs/sqlite-profiling.mdx | 63 +- vendor/actors/docs/content/docs/sqlite.mdx | 13 - vendor/actors/docs/content/docs/state.mdx | 6 - .../docs/content/docs/troubleshooting.mdx | 71 ++ .../docs/content/docs/websocket-handler.mdx | 2 - .../actors/docs/content/guides/ai-agent.mdx | 133 ++++ .../actors/docs/content/guides/arena-game.mdx | 2 +- .../docs/content/guides/authentication.mdx | 2 +- .../docs/content/guides/battle-royale.mdx | 2 +- .../actors/docs/content/guides/chat-room.mdx | 2 +- .../guides/collaborative-text-editor-ot.mdx | 2 +- .../guides/collaborative-text-editor.mdx | 2 +- .../actors/docs/content/guides/cron-jobs.mdx | 2 +- .../actors/docs/content/guides/idle-game.mdx | 2 +- vendor/actors/docs/content/guides/io-game.mdx | 2 +- .../docs/content/guides/live-cursors.mdx | 2 +- .../docs/content/guides/open-world-game.mdx | 2 +- .../actors/docs/content/guides/party-game.mdx | 2 +- .../content/guides/per-tenant-database.mdx | 2 +- .../docs/content/guides/physics-2d-game.mdx | 2 +- .../docs/content/guides/physics-3d-game.mdx | 2 +- .../docs/content/guides/ranked-game.mdx | 2 +- .../docs/content/guides/turn-based-game.mdx | 2 +- vendor/actors/docs/sidebar.json | 44 +- .../chat-room/tests/chat-room.test.ts | 91 --- .../examples/chat-room/vitest.config.ts | 10 - .../collaborative-document-ot/package.json | 4 +- .../tests/collaborative-document-ot.test.ts | 84 -- .../vitest.config.ts | 10 - .../collaborative-document/package.json | 4 +- vendor/actors/examples/cursors/package.json | 6 +- .../actors/examples/cursors/vitest.config.ts | 10 - .../actors-quickstart-next-js/app/page.tsx | 5 - .../rivet/Counter.tsx | 23 - .../actors-quickstart-next-js/rivet/node.ts | 3 - .../rivet/registry.ts | 16 - .../{ => backend}/index.ts | 0 .../{ => frontend}/Counter.tsx | 6 +- .../actors-quickstart-react/frontend/main.tsx | 9 + .../actors-versions/programmatic-version.ts | 10 - .../examples/docs/api/inspector-action.ts | 14 - .../docs/api/inspector-connections.ts | 7 - .../docs/api/inspector-database-execute.ts | 17 - .../docs/api/inspector-database-rows.ts | 12 - .../docs/api/inspector-database-schema.ts | 7 - .../docs/api/inspector-queue-delete.ts | 10 - .../examples/docs/api/inspector-queue-get.ts | 7 - .../examples/docs/api/inspector-queue-post.ts | 14 - .../examples/docs/api/inspector-rpcs.ts | 7 - .../examples/docs/api/inspector-state-get.ts | 7 - .../docs/api/inspector-state-patch.ts | 14 - .../examples/docs/api/inspector-summary.ts | 7 - .../examples/docs/api/inspector-traces.ts | 7 - .../docs/api/inspector-workflow-history.ts | 7 - .../docs/api/inspector-workflow-replay.ts | 14 - ...kers-configs-delete.ts => pools-delete.ts} | 11 +- vendor/actors/examples/docs/api/pools-get.ts | 13 + .../examples/docs/api/pools-list-nodes.ts | 14 + ...{workers-configs-list.ts => pools-list.ts} | 6 +- ...kers-configs-upsert.ts => pools-upsert.ts} | 6 +- .../actors/examples/docs/api/workers-list.ts | 12 - .../examples/docs/durable-streams/client.ts | 14 + .../examples/docs/durable-streams/create.ts | 11 + .../examples/docs/durable-streams/producer.ts | 21 + .../docs/durable-streams/read-history.ts | 10 + .../docs/durable-streams/read-live.ts | 14 + .../examples/docs/durable-streams/write.ts | 13 + .../examples/docs/general-edge/client.ts | 12 + vendor/actors/examples/docs/package.json | 4 +- vendor/actors/examples/docs/tsconfig.json | 9 +- .../multiplayer-game-patterns/package.json | 94 +-- .../src/actors/idle/world.ts | 2 +- .../matchmaking-and-session-patterns.test.ts | 717 ------------------ .../vitest.config.ts | 10 - .../examples/per-tenant-database/package.json | 4 +- .../tests/per-tenant-database.test.ts | 53 -- .../per-tenant-database/vitest.config.ts | 10 - .../scheduling/tests/scheduling.test.ts | 224 ------ .../examples/scheduling/vitest.config.ts | 7 - .../actors/examples/workflow-sdk/.env.example | 5 - .../actors/examples/workflow-sdk/package.json | 17 +- .../workflow-sdk/vitest.integration.config.ts | 11 - .../examples/workflow-sdk/vitest.setup.ts | 10 - .../workflows/order.integration.test.ts | 19 - .../artifacts/registry-config.json | 41 +- .../packages/rivetkit/package.json | 6 +- 108 files changed, 818 insertions(+), 2130 deletions(-) create mode 100644 vendor/actors/docs/content/docs/authentication.mdx delete mode 100644 vendor/actors/docs/content/docs/quickstart/next-js.mdx create mode 100644 vendor/actors/docs/content/docs/troubleshooting.mdx create mode 100644 vendor/actors/docs/content/guides/ai-agent.mdx delete mode 100644 vendor/actors/examples/chat-room/tests/chat-room.test.ts delete mode 100644 vendor/actors/examples/chat-room/vitest.config.ts delete mode 100644 vendor/actors/examples/collaborative-document-ot/tests/collaborative-document-ot.test.ts delete mode 100644 vendor/actors/examples/collaborative-document-ot/vitest.config.ts delete mode 100644 vendor/actors/examples/cursors/vitest.config.ts delete mode 100644 vendor/actors/examples/docs/actors-quickstart-next-js/app/page.tsx delete mode 100644 vendor/actors/examples/docs/actors-quickstart-next-js/rivet/Counter.tsx delete mode 100644 vendor/actors/examples/docs/actors-quickstart-next-js/rivet/node.ts delete mode 100644 vendor/actors/examples/docs/actors-quickstart-next-js/rivet/registry.ts rename vendor/actors/examples/docs/actors-quickstart-react/{ => backend}/index.ts (100%) rename vendor/actors/examples/docs/actors-quickstart-react/{ => frontend}/Counter.tsx (85%) create mode 100644 vendor/actors/examples/docs/actors-quickstart-react/frontend/main.tsx delete mode 100644 vendor/actors/examples/docs/actors-versions/programmatic-version.ts delete mode 100644 vendor/actors/examples/docs/api/inspector-action.ts delete mode 100644 vendor/actors/examples/docs/api/inspector-connections.ts delete mode 100644 vendor/actors/examples/docs/api/inspector-database-execute.ts delete mode 100644 vendor/actors/examples/docs/api/inspector-database-rows.ts delete mode 100644 vendor/actors/examples/docs/api/inspector-database-schema.ts delete mode 100644 vendor/actors/examples/docs/api/inspector-queue-delete.ts delete mode 100644 vendor/actors/examples/docs/api/inspector-queue-get.ts delete mode 100644 vendor/actors/examples/docs/api/inspector-queue-post.ts delete mode 100644 vendor/actors/examples/docs/api/inspector-rpcs.ts delete mode 100644 vendor/actors/examples/docs/api/inspector-state-get.ts delete mode 100644 vendor/actors/examples/docs/api/inspector-state-patch.ts delete mode 100644 vendor/actors/examples/docs/api/inspector-summary.ts delete mode 100644 vendor/actors/examples/docs/api/inspector-traces.ts delete mode 100644 vendor/actors/examples/docs/api/inspector-workflow-history.ts delete mode 100644 vendor/actors/examples/docs/api/inspector-workflow-replay.ts rename vendor/actors/examples/docs/api/{workers-configs-delete.ts => pools-delete.ts} (51%) create mode 100644 vendor/actors/examples/docs/api/pools-get.ts create mode 100644 vendor/actors/examples/docs/api/pools-list-nodes.ts rename vendor/actors/examples/docs/api/{workers-configs-list.ts => pools-list.ts} (63%) rename vendor/actors/examples/docs/api/{workers-configs-upsert.ts => pools-upsert.ts} (66%) delete mode 100644 vendor/actors/examples/docs/api/workers-list.ts create mode 100644 vendor/actors/examples/docs/durable-streams/client.ts create mode 100644 vendor/actors/examples/docs/durable-streams/create.ts create mode 100644 vendor/actors/examples/docs/durable-streams/producer.ts create mode 100644 vendor/actors/examples/docs/durable-streams/read-history.ts create mode 100644 vendor/actors/examples/docs/durable-streams/read-live.ts create mode 100644 vendor/actors/examples/docs/durable-streams/write.ts create mode 100644 vendor/actors/examples/docs/general-edge/client.ts delete mode 100644 vendor/actors/examples/multiplayer-game-patterns/tests/matchmaking-and-session-patterns.test.ts delete mode 100644 vendor/actors/examples/multiplayer-game-patterns/vitest.config.ts delete mode 100644 vendor/actors/examples/per-tenant-database/tests/per-tenant-database.test.ts delete mode 100644 vendor/actors/examples/per-tenant-database/vitest.config.ts delete mode 100644 vendor/actors/examples/scheduling/tests/scheduling.test.ts delete mode 100644 vendor/actors/examples/scheduling/vitest.config.ts delete mode 100644 vendor/actors/examples/workflow-sdk/.env.example delete mode 100644 vendor/actors/examples/workflow-sdk/vitest.integration.config.ts delete mode 100644 vendor/actors/examples/workflow-sdk/vitest.setup.ts delete mode 100644 vendor/actors/examples/workflow-sdk/workflows/order.integration.test.ts diff --git a/vendor/actors/docs/content/docs/actions.mdx b/vendor/actors/docs/content/docs/actions.mdx index 59b8df5d..19159c57 100644 --- a/vendor/actors/docs/content/docs/actions.mdx +++ b/vendor/actors/docs/content/docs/actions.mdx @@ -24,7 +24,7 @@ Nest actions to group related behavior: -Clients use the same path, such as `handle.users.add("Ada")`. Low-level APIs and the Inspector use the dot-separated action name `users.add`. +Clients use the same path, such as `handle.users.add("Ada")`. Low-level APIs use the dot-separated action name `users.add`. ## Calling Actions @@ -37,13 +37,6 @@ Actions can be called in different ways depending on your use case: Learn more about [communicating with actors from the frontend](/actors/docs/communicating-between-actors). - - - - - -Learn more about [communicating with actors from the backend](/actors/docs/communicating-between-actors). - @@ -127,13 +120,3 @@ Rivet provides the `ActionContextOf` utility type for exactly this purpose: See [types](/actors/docs/types) for more details on using `ActionContextOf` and other utility types. - -{/* TODO(code): restore when the control plane exposes an API to read an Actor's inspector token. Tracked in ACT-6493. - -## Debugging - -- `GET /inspector/rpcs` lists all available actions on an actor. -- `POST /inspector/action/:name` executes an action with JSON args and returns output. -- In non-dev mode, inspector endpoints require authorization. - -*/} diff --git a/vendor/actors/docs/content/docs/appearance.mdx b/vendor/actors/docs/content/docs/appearance.mdx index 3d26fab0..012aa92b 100644 --- a/vendor/actors/docs/content/docs/appearance.mdx +++ b/vendor/actors/docs/content/docs/appearance.mdx @@ -1,10 +1,10 @@ --- title: Icons & Names -description: "Configure display names and icons for Rivet Actors so each instance is easy to recognize in the inspector." +description: "Configure display names and icons for Rivet Actors so each instance is easy to recognize in the Rivet dashboard." skill: true --- -Actors can be customized with a display name and icon that appear in the Rivet inspector. This helps identify actors at a glance when managing your application. +Actors can be customized with a display name and icon that appear in the Rivet dashboard. This helps identify actors at a glance when managing your application. ## Configuration @@ -50,7 +50,7 @@ Users can then use this directly: -This run-handler metadata is applied through the registry metadata. The native runtime and inspector config read the actor's `options.name` and `options.icon` directly, so set those explicitly if you need the name or icon to appear everywhere. +This run-handler metadata is applied through the registry metadata. The native runtime reads the actor's `options.name` and `options.icon` directly, so set those explicitly if you need the name or icon to appear everywhere. Actor-level `options.name` and `options.icon` always take precedence, allowing users to override library defaults: diff --git a/vendor/actors/docs/content/docs/authentication.mdx b/vendor/actors/docs/content/docs/authentication.mdx new file mode 100644 index 00000000..90a948c9 --- /dev/null +++ b/vendor/actors/docs/content/docs/authentication.mdx @@ -0,0 +1,129 @@ +--- +title: "Authentication" +description: "Authenticate Rivet Actor connections, validate credentials before clients connect, and carry trusted identity into actor actions." +skill: true +--- + +## Do You Need Authentication? + + + + Actors are private by default on Rivet Cloud. Only requests with the publishable token can interact with actors. + + - **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. + + + Control plane authentication is required by default on self-hosted Rivet. Configure an admin token on the control plane and issue scoped tokens for clients. + + See [Authentication](/docs/authentication) for credentials and [Scoped Tokens](/docs/jwt) for permissions. + + + +## Issue access tokens + +Keep the control plane's admin credential on your backend. Issue [scoped tokens](/docs/jwt) for clients, granting only the resources and operations they need in their namespace. Actor traffic uses `actor_gateway` permissions; Actor creation and lookup use `actor` permissions. + +Control plane grants decide which Actors a client can reach. The connection hooks below can also check your application's user identity and permissions. + +## 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` + +## Access Control + +After a connection is authenticated, use [Access Control](/actors/docs/access-control) to enforce authorization: + +- Check permissions in action handlers. +- Use `queues..canPublish` to gate inbound queue publishes. +- Use `events..canSubscribe` to gate event subscriptions. + +### `onBeforeConnect` + +The `onBeforeConnect` hook validates credentials before allowing a connection. Throw an error to reject the connection. + + + +### `createConnState` + +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](/actors/docs/connections) for more details. + + + +## Available Auth Data + +Authentication hooks have access to several properties: + +| Property | Description | +|----------|-------------| +| `params` | Custom data passed by the client when connecting (see [connection params](/actors/docs/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](/actors/docs/state)) | +| `c.key` | The actor's key (see [keys](/actors/docs/keys)) | + +It's recommended to use `params` instead of `c.request.headers` whenever possible since it works for both HTTP & WebSocket connections. + +## Client Usage + +### Passing Credentials + +Pass authentication data when connecting. Use `getParams` when you need a fresh JWT for every connection or reconnect: + + + + + + + +### Handling Errors + +Authentication errors use the same system as regular errors. See [errors](/actors/docs/errors) for more details. + + + + + + +## Examples + +### JWT + +Validate JSON Web Tokens and extract user claims: + + + +### External Auth Provider + +Validate credentials against an external authentication service: + + + +### Using `c.state` In Authorization + +Access actor state via `c.state` and the actor's key via `c.key` to make authorization decisions: + + + +### Role-Based Access Control + +Create helper functions for common authorization patterns: + + + +### Rate Limiting + +Use `c.vars` to track connection attempts and rate limit by user: + + + +The limits in this example are [ephemeral](/actors/docs/state#ephemeral-variables). If you wish to persist rate limits, you can optionally replace `vars` with `state`. + +### Caching Tokens + +Cache validated tokens in `c.vars` to avoid redundant validation on repeated connections. See [ephemeral variables](/actors/docs/state#ephemeral-variables) for more details. + + diff --git a/vendor/actors/docs/content/docs/clients/javascript.mdx b/vendor/actors/docs/content/docs/clients/javascript.mdx index 589ac711..355f3ad4 100644 --- a/vendor/actors/docs/content/docs/clients/javascript.mdx +++ b/vendor/actors/docs/content/docs/clients/javascript.mdx @@ -41,6 +41,8 @@ Use `params` for static connection parameters. Use `getParams` when the value ca +Transient connection failures trigger reconnection. Actions rejected during a disconnect are removed from the outbound queue; a request already sent can have an unknown outcome. Use application-level idempotency before retrying mutations. A permanent connection-opening failure rejects subsequent calls on that connection; create a new connection after correcting the cause. + ## Low-Level HTTP & WebSocket For actors that implement `onRequest` or `onWebSocket`, call them directly: @@ -100,7 +102,7 @@ Endpoints support URL auth syntax: https://namespace:token@rivet.example.com ``` -You can also pass the endpoint without auth and provide `RIVET_NAMESPACE` and `RIVET_TOKEN` separately. See [Endpoints](/docs/connect#url-auth-syntax) for details. +You can also pass the endpoint without auth and provide `RIVET_NAMESPACE` and `RIVET_TOKEN` separately. See [Endpoints](/docs/endpoints#url-auth-syntax) for details. ## Advanced diff --git a/vendor/actors/docs/content/docs/clients/react.mdx b/vendor/actors/docs/content/docs/clients/react.mdx index f2eccb71..c60599e9 100644 --- a/vendor/actors/docs/content/docs/clients/react.mdx +++ b/vendor/actors/docs/content/docs/clients/react.mdx @@ -102,7 +102,7 @@ Endpoints support URL auth syntax: https://namespace:token@rivet.example.com ``` -You can also pass the endpoint without auth and provide `RIVET_NAMESPACE` and `RIVET_TOKEN` separately. See [Endpoints](/docs/connect#url-auth-syntax) for details. +You can also pass the endpoint without auth and provide `RIVET_NAMESPACE` and `RIVET_TOKEN` separately. See [Endpoints](/docs/endpoints#url-auth-syntax) for details. ## API Reference diff --git a/vendor/actors/docs/content/docs/clients/rust.mdx b/vendor/actors/docs/content/docs/clients/rust.mdx index 44ad6cd9..f2f9b4a7 100644 --- a/vendor/actors/docs/content/docs/clients/rust.mdx +++ b/vendor/actors/docs/content/docs/clients/rust.mdx @@ -36,7 +36,7 @@ use rivetkit::{ #[tokio::main] async fn main() -> Result<()> { - let client = Client::new(ClientConfig::new("http://localhost:6420").namespace("default")); + let client = Client::new(ClientConfig::new("http://localhost:6420")); let counter = client.get_or_create_typed_default::("counter", ["my-counter"])?; let count = counter.send(Increment { amount: 1 }).await?; @@ -60,7 +60,7 @@ use rivetkit::{ #[tokio::main] async fn main() -> Result<()> { - let client = Client::new(ClientConfig::new("http://localhost:6420").namespace("default")); + let client = Client::new(ClientConfig::new("http://localhost:6420")); let counter = client.get_or_create_typed_default::("counter", ["my-counter"])?; // Stateless: each call is independent @@ -93,7 +93,7 @@ use serde_json::json; #[tokio::main] async fn main() -> Result<()> { - let client = Client::new(ClientConfig::new("http://localhost:6420").namespace("default")); + let client = Client::new(ClientConfig::new("http://localhost:6420")); // Get or create an actor let room = client.get_or_create_typed_default::("counter", ["room-42"])?; @@ -139,7 +139,7 @@ use serde_json::json; #[tokio::main] async fn main() -> Result<()> { - let client = Client::new(ClientConfig::new("http://localhost:6420").namespace("default")); + let client = Client::new(ClientConfig::new("http://localhost:6420")); let chat = client.get_or_create_typed::( "counter", @@ -170,7 +170,7 @@ use rivetkit::{ #[tokio::main] async fn main() -> Result<()> { - let client = Client::new(ClientConfig::new("http://localhost:6420").namespace("default")); + let client = Client::new(ClientConfig::new("http://localhost:6420")); let connection = client .get_or_create_typed_default::("counter", ["general"])? .connect(); @@ -199,7 +199,7 @@ use rivetkit::{ #[tokio::main] async fn main() -> Result<()> { - let client = Client::new(ClientConfig::new("http://localhost:6420").namespace("default")); + let client = Client::new(ClientConfig::new("http://localhost:6420")); let connection = client .get_or_create_typed_default::("counter", ["general"])? .connect(); @@ -243,7 +243,7 @@ use tokio_tungstenite::tungstenite::Message; #[tokio::main] async fn main() -> Result<()> { - let client = Client::new(ClientConfig::new("http://localhost:6420").namespace("default")); + let client = Client::new(ClientConfig::new("http://localhost:6420")); let handle = client.get_or_create_typed_default::("counter", ["general"])?; // Raw HTTP request @@ -298,7 +298,7 @@ use rivetkit::{ #[tokio::main] async fn main() -> Result<()> { - let client = Client::new(ClientConfig::new("http://localhost:6420").namespace("default")); + let client = Client::new(ClientConfig::new("http://localhost:6420")); let counter = client.get_or_create_typed_default::("counter", ["my-counter"])?; match counter.send(Increment { amount: 1 }).await { @@ -326,7 +326,7 @@ use rivetkit::{ #[tokio::main] async fn main() -> Result<()> { - let client = Client::new(ClientConfig::new("http://localhost:6420").namespace("default")); + let client = Client::new(ClientConfig::new("http://localhost:6420")); // Compound key: [org, room] let room = client.get_or_create_typed_default::("counter", ["org-acme", "general"])?; @@ -341,25 +341,27 @@ Keys accept arrays of `&str` or `String` (`["org-acme", "general"]`). Don't buil ### Configuration -`ClientConfig::new(endpoint)` is a builder. The endpoint is always required; there is no default. Common options: +`ClientConfig::new(endpoint)` is a builder. The endpoint is always required; there is no default. It accepts the same URL auth syntax as `RIVET_ENDPOINT`, so `https://my-namespace:my-token@api.rivet.dev` sets the namespace and token in one value. Common options: ```rust @nocheck use rivetkit::client::ClientConfig; -let config = ClientConfig::new("http://localhost:6420") - .namespace("default") +let config = ClientConfig::new("https://api.rivet.dev") + .namespace("my-namespace") .token("") .pool_name("my-pool") .header("x-custom", "value"); ``` -- `namespace` - target namespace (defaults to the control plane's configured namespace). -- `token` - authentication token for the control plane. -- `pool_name` - node pool to target. +- `namespace` - target namespace. Falls back to `RIVET_NAMESPACE`, then `default`. +- `token` - authentication token for the control plane. Falls back to `RIVET_TOKEN`. A local control plane (`localhost` or a loopback address) uses the `default` token automatically, which is why the quickstart passes only an endpoint. +- `pool_name` - node pool new actors are created in. Falls back to `RIVET_POOL`, then `default`, which matches the pool a `Registry` joins when `RIVET_POOL` is unset. - `header` / `headers` - extra HTTP headers sent with each request. - `max_input_size` - cap on encoded action input size. -See [Endpoints](/docs/connect) for details. +If the endpoint is not a valid URL, or a namespace or token is given both in the endpoint URL and as a separate option, every call on the client returns that error. + +See [Endpoints](/docs/endpoints) for details. ## API Reference diff --git a/vendor/actors/docs/content/docs/clients/swift.mdx b/vendor/actors/docs/content/docs/clients/swift.mdx index a262a389..b59422e9 100644 --- a/vendor/actors/docs/content/docs/clients/swift.mdx +++ b/vendor/actors/docs/content/docs/clients/swift.mdx @@ -423,7 +423,7 @@ Endpoints support URL auth syntax: https://namespace:token@rivet.example.com ``` -You can also pass the endpoint without auth and provide `RIVET_NAMESPACE` and `RIVET_TOKEN` separately. See [Endpoints](/docs/connect#url-auth-syntax) for details. +You can also pass the endpoint without auth and provide `RIVET_NAMESPACE` and `RIVET_TOKEN` separately. See [Endpoints](/docs/endpoints#url-auth-syntax) for details. ## API Reference diff --git a/vendor/actors/docs/content/docs/clients/swiftui.mdx b/vendor/actors/docs/content/docs/clients/swiftui.mdx index 0493e0b5..030bd31e 100644 --- a/vendor/actors/docs/content/docs/clients/swiftui.mdx +++ b/vendor/actors/docs/content/docs/clients/swiftui.mdx @@ -330,7 +330,7 @@ Endpoints support URL auth syntax: https://namespace:token@rivet.example.com ``` -You can also pass the endpoint without auth and provide `RIVET_NAMESPACE` and `RIVET_TOKEN` separately. See [Endpoints](/docs/connect#url-auth-syntax) for details. +You can also pass the endpoint without auth and provide `RIVET_NAMESPACE` and `RIVET_TOKEN` separately. See [Endpoints](/docs/endpoints#url-auth-syntax) for details. ## API Reference diff --git a/vendor/actors/docs/content/docs/debugging.mdx b/vendor/actors/docs/content/docs/debugging.mdx index 5f682f27..d9bb507c 100644 --- a/vendor/actors/docs/content/docs/debugging.mdx +++ b/vendor/actors/docs/content/docs/debugging.mdx @@ -30,28 +30,6 @@ Standard actor endpoints (health, actions, requests) use the same authentication | **Self-hosted** | The Rivet control plane handles authentication at the gateway level. | | **Rivet Cloud** | Authentication is handled by the Rivet Cloud platform at the gateway level. | -{/* TODO(code): restore when the control plane exposes an API to read an Actor's inspector token. Tracked in ACT-6493. - -### Inspector Endpoints - -Each actor generates a unique inspector token on first start and stores it with its data. Pass it as a bearer token in the `Authorization` header. - -Inspector endpoints always require the actor's inspector token, including in local development. There is no local-development bypass. - -| Environment | Authentication | -|---|---| -| **Local development** | Bearer the actor's inspector token in the `Authorization` header. | -| **Self-hosted** | Bearer the actor's inspector token in the `Authorization` header. | - -```bash -curl "$RIVET_API/gateway/{actor_id}/inspector/summary" \ - -H 'Authorization: Bearer YOUR_INSPECTOR_TOKEN' -``` - -### Retrieving the Inspector Token - -*/} - ## Standard Actor Endpoints These are the built-in actor endpoints available through the gateway: @@ -95,289 +73,3 @@ The `response` field is only present when the queue handler returns a value: ``` If `wait: true` and the timeout is reached, `status` is `"timedOut"`. - -{/* TODO(code): restore when the control plane exposes an API to read an Actor's inspector token. Tracked in ACT-6493. - -## Inspector Endpoints - -The inspector HTTP API exposes JSON endpoints for querying and modifying actor internals at runtime. These are designed for agent-based debugging and tooling. - -Every inspector endpoint requires the actor's inspector token as a bearer token, including in local development. The examples below omit the `Authorization` header for brevity, but you must add `-H "Authorization: Bearer $INSPECTOR_TOKEN"` to each request. See [Retrieving the Inspector Token](#retrieving-the-inspector-token) above. - -### Get State - -```bash -curl $RIVET_API/gateway/{actor_id}/inspector/state -``` - -Returns the actor's current persisted state: - -```json -{ - "state": { "count": 42, "users": [] }, - "isStateEnabled": true -} -``` - -### Set State - -```bash -curl -X PATCH $RIVET_API/gateway/{actor_id}/inspector/state \ - -H 'Content-Type: application/json' \ - -d '{"state": {"count": 0, "users": []}}' -``` - -Returns: - -```json -{ "ok": true } -``` - -### Get Connections - -```bash -curl $RIVET_API/gateway/{actor_id}/inspector/connections -``` - -Returns all active connections with their params, state, and metadata: - -```json -{ - "connections": [ - { - "type": "websocket", - "id": "conn-id", - "details": { - "type": "websocket", - "params": {}, - "stateEnabled": true, - "state": {}, - "subscriptions": 2, - "isHibernatable": true - } - } - ] -} -``` - -### Get RPCs - -```bash -curl $RIVET_API/gateway/{actor_id}/inspector/rpcs -``` - -Returns a list of available actions: - -```json -{ "rpcs": ["increment", "getCount"] } -``` - -### Execute Action - -```bash -curl -X POST $RIVET_API/gateway/{actor_id}/inspector/action/increment \ - -H 'Content-Type: application/json' \ - -d '{"args": [5]}' -``` - -Returns: - -```json -{ "output": 47 } -``` - -### Get Queue Status - -```bash -curl $RIVET_API/gateway/{actor_id}/inspector/queue?limit=10 -``` - -Returns queue status with messages: - -```json -{ - "size": 3, - "maxSize": 1000, - "truncated": false, - "messages": [ - { "id": 1, "name": "process", "createdAtMs": 1706000000000 } - ] -} -``` - -### Get Workflow History - -```bash -curl $RIVET_API/gateway/{actor_id}/inspector/workflow-history -``` - -Returns: - -```json -{ - "history": null, - "isWorkflowEnabled": false -} -``` - -### Get Database Schema - -```bash -curl $RIVET_API/gateway/{actor_id}/inspector/database/schema -``` - -Returns discovered SQLite tables and views when the actor has `c.db` enabled: - -```json -{ - "schema": { - "tables": [ - { - "table": { "schema": "main", "name": "test_data", "type": "table" }, - "columns": [ - { "cid": 0, "name": "id", "type": "", "notnull": 0, "dflt_value": null, "pk": 0 } - ], - "foreignKeys": [], - "records": 2 - } - ] - } -} -``` - -### Get Database Rows - -```bash -curl "$RIVET_API/gateway/{actor_id}/inspector/database/rows?table=test_data&limit=100&offset=0" -``` - -Returns paged rows for a specific SQLite table or view: - -```json -{ - "rows": [ - { - "id": 1, - "value": "Alice", - "payload": "", - "created_at": 1706000000000 - } - ] -} -``` - -### Execute SQLite - -Run manual SQL against an actor's SQLite database. This supports both read-only queries and mutations. - -```bash -curl -X POST http://localhost:6420/gateway/{actor_id}/inspector/database/execute \ - -H 'Content-Type: application/json' \ - -d '{ - "sql": "SELECT id, value FROM test_data WHERE value = ? ORDER BY id DESC", - "args": ["alpha"] - }' -``` - -Returns: - -```json -{ - "rows": [ - { "id": 2, "value": "alpha" } - ] -} -``` - -You can also use named SQLite bindings through a `properties` object: - -```bash -curl -X POST http://localhost:6420/gateway/{actor_id}/inspector/database/execute \ - -H 'Content-Type: application/json' \ - -d '{ - "sql": "SELECT id, value FROM test_data WHERE value = :value ORDER BY id DESC", - "properties": { - "value": "alpha" - } - }' -``` - -For mutations, use `RETURNING` if you want rows back. Otherwise the statement still runs and `rows` is empty: - -```bash -curl -X POST http://localhost:6420/gateway/{actor_id}/inspector/database/execute \ - -H 'Content-Type: application/json' \ - -d '{ - "sql": "INSERT INTO test_data (value, created_at) VALUES (?, ?) RETURNING id, value", - "args": ["beta", 1706000000000] - }' -``` - -For workflow-enabled actors, `history` is a JSON object with `nameRegistry`, `entries`, and `entryMetadata`. Step outputs, loop state, and message payloads are decoded from CBOR into normal JSON values. - -### Replay Workflow From Step - -Reset a workflow to a specific step and restart execution immediately. Omitting `entryId` replays the workflow from the beginning. - -If the workflow is still running when you call replay, the endpoint rejects the request with `409 Conflict` and an `actor/workflow_in_flight` error instead of cancelling the live run for you. - -```bash -curl -X POST http://localhost:6420/gateway/{actor_id}/inspector/workflow/replay \ - -H 'Content-Type: application/json' \ - -d '{"entryId":"workflow-step-id"}' -``` - -Returns the same JSON shape as `/inspector/workflow-history`: - -```json -{ - "history": { - "nameRegistry": ["step-one", "step-two"], - "entries": [], - "entryMetadata": {} - }, - "isWorkflowEnabled": true -} -``` - -While a workflow is in flight, the response shape is: - -```json -{ - "group": "actor", - "code": "workflow_in_flight", - "message": "Workflow replay is unavailable while the workflow is currently in flight.", - "metadata": null -} -``` - -### Summary - -Get a full snapshot of the actor in a single request: - -```bash -curl $RIVET_API/gateway/{actor_id}/inspector/summary -``` - -Returns: - -```json -{ - "state": { "count": 42 }, - "connections": [], - "rpcs": ["increment", "getCount"], - "queueSize": 0, - "isStateEnabled": true, - "isDatabaseEnabled": false, - "isWorkflowEnabled": false, - "workflowHistory": null -} -``` - -When workflow history is present in `/inspector/summary`, `workflowHistory` is returned as the same decoded JSON shape as `/inspector/workflow-history`. - -## Polling - -Inspector endpoints are safe to poll. For live monitoring, poll at 1-5 second intervals. The `/inspector/summary` endpoint is useful for periodic snapshots since it returns all data in a single request. - -*/} diff --git a/vendor/actors/docs/content/docs/environment-variables.mdx b/vendor/actors/docs/content/docs/environment-variables.mdx index b252bdf9..1c3bbe5a 100644 --- a/vendor/actors/docs/content/docs/environment-variables.mdx +++ b/vendor/actors/docs/content/docs/environment-variables.mdx @@ -1,6 +1,6 @@ --- title: "Environment Variables" -description: "Configure RivetKit runtime behavior with environment variables for the inspector, storage, and logging." +description: "Configure RivetKit runtime behavior with environment variables for metrics, storage, and logging." skill: true --- @@ -9,11 +9,11 @@ connect your node to a Rivet control plane, select a node pool, or configure the local control plane live in [Environment Variables](/docs/environment-variables) in the platform docs. -## Inspector +## Metrics | Environment Variable | Description | |---------------------|-------------| -| `RIVET_INSPECTOR_DISABLE` | Set to `1` to disable the inspector | +| `_RIVET_METRICS_TOKEN` | Bearer token that gates the per-actor Prometheus `/metrics` endpoint. When unset, `/metrics` is disabled. | ## Experimental diff --git a/vendor/actors/docs/content/docs/events.mdx b/vendor/actors/docs/content/docs/events.mdx index b1b9d5d4..a3c686f6 100644 --- a/vendor/actors/docs/content/docs/events.mdx +++ b/vendor/actors/docs/content/docs/events.mdx @@ -142,17 +142,6 @@ function ConditionalListener() { -{/* TODO(code): restore when the control plane exposes an API to read an Actor's inspector token. Tracked in ACT-6493. - -## Debugging - -- `GET /inspector/connections` shows active connections and connection metadata. -- Use this to confirm clients are connected before expecting broadcasts. -- `GET /inspector/summary` provides connections, RPCs, and queue size in one response. -- In non-dev mode, inspector endpoints require authorization. - -*/} - ## More About Connections For more details on actor connections, including connection lifecycle, authentication, and advanced connection patterns, see the [Connections documentation](/actors/docs/connections). diff --git a/vendor/actors/docs/content/docs/http-server.mdx b/vendor/actors/docs/content/docs/http-server.mdx index 00f4b363..e48d2a65 100644 --- a/vendor/actors/docs/content/docs/http-server.mdx +++ b/vendor/actors/docs/content/docs/http-server.mdx @@ -12,7 +12,7 @@ Call `registry.start()` to connect your app to the control plane and run Actors: Run the file with `npx tsx --watch index.ts` for Node.js, or `bun --watch index.ts` for Bun. In local development, RivetKit starts a control plane at `http://localhost:6420`. Actor clients connect to that control plane. -In production, set [RIVET_ENDPOINT](/docs/connect) and run the process continuously. See [Deploy Nodes](/docs/deploy/self-host/nodes/). +In production, set [RIVET_ENDPOINT](/docs/endpoints) and run the process continuously. See [Deploy Nodes](/docs/deploy/self-host/workers/). ## Add health and metrics routes diff --git a/vendor/actors/docs/content/docs/limits.mdx b/vendor/actors/docs/content/docs/limits.mdx index 3f882889..f96ac991 100644 --- a/vendor/actors/docs/content/docs/limits.mdx +++ b/vendor/actors/docs/content/docs/limits.mdx @@ -22,15 +22,19 @@ Per-actor limits such as queue sizes and lifecycle timeouts are passed to `actor ## Limits +{/* TODO(verify): check every hard limit on this page against the current control plane. The gateway and WebSocket numbers were written for the previous engine and have not been rechecked. */} + ### WebSocket These limits affect actions that use `.connect()` and [low-level WebSockets](/actors/docs/websocket-handler). | Name | Soft Limit | Hard Limit | Description | |------|------------|------------|-------------| -| Max incoming message size | 64 KiB | 16 MiB | Maximum size of incoming WebSocket messages. Soft limit configurable via `maxIncomingMessageSize`. | -| Max outgoing message size | 1 MiB | 16 MiB | Maximum size of outgoing WebSocket messages. Soft limit configurable via `maxOutgoingMessageSize`. | -| WebSocket open timeout | N/A | 15 seconds | Time allowed to authorize the connection and reach the actor. | +| Max incoming message size | 64 KiB | 32 MiB | Maximum size of incoming WebSocket messages. Soft limit configurable via `maxIncomingMessageSize`. | +| Max outgoing message size | 1 MiB | 32 MiB | Maximum size of outgoing WebSocket messages. Soft limit configurable via `maxOutgoingMessageSize`. | +| Max WebSocket frame size | N/A | 32 MiB | Maximum size of a single WebSocket frame accepted by Rivet's transport edge. This is not configurable by browser clients and is not negotiated during the WebSocket handshake. | +| WebSocket open timeout | N/A | 15 seconds | Time allowed for WebSocket connection to be established, including `onBeforeConnect` and `createConnState` hooks. Connection is closed if exceeded. | +| Message ack timeout | N/A | 30 seconds | Time allowed for message acknowledgment before connection is closed. Only relevant in the case of a network issue and does not affect your application. | WebSocket connections close when the actor sleeps. Clients reconnect, which wakes the actor. @@ -40,10 +44,9 @@ These limits affect actions that do not use `.connect()` and [low-level HTTP req | Name | Soft Limit | Hard Limit | Description | |------|------------|------------|-------------| -| Actor start wait | N/A | 45 seconds | Maximum time a request waits for its actor to start before it fails. | -| Max buffered response body size | N/A | 16 MiB | Maximum size of a non-streaming HTTP response. Streaming responses are flow controlled and may transfer more over their lifetime. | -| Response start timeout | 60 seconds | N/A | Maximum time for `onRequest` to return response headers. Uses `actionTimeout`. It does not limit a response stream after the headers arrive. | -| Streaming response idle timeout | N/A | None | Rivet does not close an otherwise healthy stream because no body chunk was produced. Other proxies and hosting platforms may impose their own idle timeouts, so SSE handlers should send periodic comment heartbeats. | +| Max pending buffer size | N/A | 128 MiB | Total size of all buffered messages per connection while actor is sleeping. | +| Max pending message count | N/A | 65,535 | Maximum number of buffered messages per connection while actor is sleeping. | +| Hibernation timeout | N/A | 90 seconds | Maximum time an actor has to wake up before the client is disconnected. Only relevant if something is wrong with starting actors. | Request bodies are streamed to the actor and have no fixed size limit. @@ -51,18 +54,29 @@ Request bodies are streamed to the actor and have no fixed size limit. | Name | Soft Limit | Hard Limit | Description | |------|------------|------------|-------------| -| Max queue size | 1,000 messages | N/A | Maximum number of messages in the queue before new messages are rejected. Configurable via `maxQueueSize`. | -| Max queue message size | 64 KiB | N/A | Maximum size of each individual queue message. Configurable via `maxQueueMessageSize`. | +| Max request body size | N/A | 20 MiB | Maximum size of HTTP request bodies. | +| Max buffered response body size | N/A | 20 MiB | Maximum size of a non-streaming HTTP response. Streaming responses may transfer more than 20 MiB over their lifetime and are flow controlled instead of buffered in full. | +| Response start timeout | N/A | 5 minutes by default | Maximum time for `onRequest` to return response headers. It does not limit the lifetime of a response stream after the headers arrive. | +| Streaming response idle timeout | N/A | None by default | Rivet does not close an otherwise healthy stream because no body chunk was produced. Other proxies and hosting platforms may impose their own idle timeouts, so SSE handlers should send periodic comment heartbeats. | ### Schedule | Name | Soft Limit | Hard Limit | Description | |------|------------|------------|-------------| -| Max scheduled events | 1,000 | N/A | Maximum number of pending scheduled events per actor. Configurable via `maxSchedules`. | +| Connection ping timeout | N/A | 30 seconds | Connection is closed if a ping is not acknowledged within this time. Applies to both HTTP and WebSocket. Only relevant in the case of a network issue and does not affect your application. | + +### Actor Storage + +| Name | Soft Limit | Hard Limit | Description | +|------|------------|------------|-------------| +| Max queue size | 1,000 messages | N/A | Maximum number of messages in the queue before new messages are rejected. Configurable via `maxQueueSize`. | +| Max queue message size | 64 KiB | 128 KiB (effective) | Maximum size of each individual queue message. Configurable via `maxQueueMessageSize`. Actual payload is slightly lower after queue serialization overhead. | ### Actor Storage -Each Rivet Actor has one durable volume. Its [SQLite database](/actors/docs/sqlite) and its [KV](/actors/docs/kv) data live in that volume. +Each Rivet Actor has one durable volume. Its [SQLite database](/actors/docs/sqlite) and its [KV](/actors/docs/kv) data live in that volume, so they share one storage limit. + +{/* TODO(verify): confirm the per-actor storage cap and the KV key and value caps are enforced on the current control plane. */} ### Actor KV Storage @@ -72,20 +86,21 @@ These limits apply to the [KV API](/actors/docs/kv). |------|------------|------------|-------------| | Max key size | N/A | 2 KiB | Maximum size of a single key. | | Max value size | N/A | 128 KiB | Maximum size of a single value. | - -A large batch put is split into several transactions, so it is not atomic. Keep entries that must change together in one small batch. +| Max keys per operation | N/A | 128 | Maximum number of keys in a single batch get/put/delete operation. Does not apply to range operations (`listRange`, `deleteRange`). | +| Max batch put payload size | N/A | 976 KiB | Maximum total size of all key-value pairs in a single batch put operation. | +| Max storage size per actor | N/A | 10 GiB | Maximum total storage of a single Rivet Actor, shared with SQLite. | +| List default limit | N/A | 16,384 | Default maximum number of keys returned by a list operation. | ### Actor SQLite Storage -These limits apply to the [SQLite database](/actors/docs/sqlite). +These limits apply to the [SQLite database](/actors/docs/sqlite). It shares the Rivet Actor's storage limit with KV. | Name | Soft Limit | Hard Limit | Description | |------|------------|------------|-------------| +| Max storage size per actor | N/A | 10 GiB | Maximum total storage size for a single actor. This limit is shared with KV storage. | | Max pages changed per transaction | N/A | 32,768 pages (128 MiB) | Maximum SQLite pages one transaction can change, at 4 KiB per page. A larger transaction fails with `sqlite.transaction_too_large` and is rolled back; the database stays usable. | | Transaction deadline | 60 seconds | N/A | Safety backstop for `db.transaction()`. Configure per transaction with `{ timeout: milliseconds }`; there is no product-level maximum. | | Transaction coordinator queue | N/A | 128 operations | Maximum admitted SQLite operations waiting behind an active coordinated transaction. Additional operations fail with `sqlite.transaction_queue_full`. | -| Max database size (remote SQL) | N/A | 256 MiB (65,536 pages) | Applies when queries run on the control plane: always on the WebAssembly runtime, and on native runtimes with `sqlite.backend` set to `"remote"`. | -| Max value and result size (remote SQL) | N/A | 24 MiB | Maximum size of one value and of one statement's result when queries run on the control plane. | Large commits are sent in internal chunks, but each transaction is published atomically. The limit counts raw pages changed, before compression. @@ -99,19 +114,32 @@ The Beta [Actor Runtime Socket](/actors/docs/actor-runtime-socket) negotiates it |------|------------|------------|-------------| | Frame payload size | 32 MiB | N/A | Default maximum request or response payload. Self-hosted native runtimes can configure `RIVET_ACTOR_RUNTIME_SOCKET_MAX_FRAME_BYTES`; oversized responses return `ResponseTooLarge`. | +### Startup Preloading + +When a Rivet Actor starts, RivetKit loads some of its own data in the same step as the start, to save round trips. Per-actor overrides are set via `options`. + +| Name | Soft Limit | Hard Limit | Description | +|------|------------|------------|-------------| +| Max workflow preload size | 128 KiB | N/A | Default maximum size of preloaded workflow data for RivetKit actors. Configurable per actor via `options.preloadMaxWorkflowBytes`. Setting to 0 disables workflow preloading for that actor. | +| Max connections preload size | 64 KiB | N/A | Default maximum size of preloaded connection data for RivetKit actors. Configurable per actor via `options.preloadMaxConnectionsBytes`. Setting to 0 disables connections preloading for that actor. | + ### Names and Keys | Name | Soft Limit | Hard Limit | Description | |------|------------|------------|-------------| -| Max actor key total size | N/A | 1,024 bytes | Maximum total size of the serialized actor key. | -| Max actor name length | N/A | 64 bytes | Maximum length of an actor name. | -| Max namespace and pool name length | N/A | 63 bytes | Maximum length of a namespace slug or node pool name. | +| Max actor input size | N/A | 1 MiB | Maximum size of the input passed when creating an actor. | +| Max connection params size | N/A | 4 KiB | Maximum size of connection parameters passed when connecting to an actor. | +| Max actor key component size | N/A | 128 bytes | Maximum size of each component in an actor key array. | +| Max actor key total size | N/A | 1,024 bytes | Maximum total size of the serialized actor key string. | +| Max actor name length | N/A | 64 characters | Maximum length for actor and project identifiers. | ### Timeouts | Name | Soft Limit | Hard Limit | Description | |------|------------|------------|-------------| -| Action timeout | 60 seconds | N/A | Timeout for RPC actions and for raw `onRequest` handlers to return response headers. Configurable via `actionTimeout`. | +| Action timeout | 60 seconds | N/A | Timeout for RPC actions. Configurable via `actionTimeout`. | +| Raw HTTP response start timeout | N/A | 5 minutes by default | Time allowed for a raw `onRequest` handler to return response headers. `actionTimeout` does not apply to raw HTTP handlers, and a streaming response has no fixed total-duration timeout after it starts. | +| Raw HTTP stream idle timeout | N/A | None by default | Rivet does not close a stream for producing no chunks. Other proxies may, so send SSE heartbeats. | | On before connect timeout | 5 seconds | N/A | Timeout for the `onBeforeConnect` hook. Configurable via `onBeforeConnectTimeout`. | | Create vars timeout | 5 seconds | N/A | Timeout for `createVars` hook. Configurable via `createVarsTimeout`. | | Create conn state timeout | 5 seconds | N/A | Timeout for `createConnState` hook. Configurable via `createConnStateTimeout`. | @@ -127,8 +155,8 @@ The Beta [Actor Runtime Socket](/actors/docs/actor-runtime-socket) negotiates it | Name | Soft Limit | Hard Limit | Description | |------|------------|------------|-------------| -| Actor start threshold | N/A | 15 seconds | Maximum time for an actor to start. A start that takes longer is stopped. | -| Node lost threshold | N/A | 40 seconds | Time after a node's connection drops before its actors are rescheduled on other nodes. | +| Actor start threshold | N/A | 30 seconds | Maximum time for an actor to report running after its start is sent before the start is given up and retried. | +| Actor stop threshold | N/A | 30 minutes | Time a node is given to stop its actors once asked. RivetKit uses it as the default shutdown grace period. | ## Increasing Limits diff --git a/vendor/actors/docs/content/docs/production-checklist.mdx b/vendor/actors/docs/content/docs/production-checklist.mdx index 28aeb61b..6f636358 100644 --- a/vendor/actors/docs/content/docs/production-checklist.mdx +++ b/vendor/actors/docs/content/docs/production-checklist.mdx @@ -10,7 +10,7 @@ We recommend passing this page to your coding agent to verify your configuration Deploy-time configuration (environment variables, node pools and graceful shutdown) lives in the -[self-host production checklist](/docs/deploy/self-host/nodes/production-checklist/). +[self-host production checklist](/docs/deploy/self-host/workers/production-checklist/). This page covers application design: what to get right before writing the actor, not before shipping it. diff --git a/vendor/actors/docs/content/docs/queues.mdx b/vendor/actors/docs/content/docs/queues.mdx index 6b476490..55053686 100644 --- a/vendor/actors/docs/content/docs/queues.mdx +++ b/vendor/actors/docs/content/docs/queues.mdx @@ -115,17 +115,6 @@ If an actor has a `run` handler, it does not sleep while that handler is activel This means you can run normal code in `run` without worrying about sleep interrupting it mid-call. -{/* TODO(code): restore when the control plane exposes an API to read an Actor's inspector token. Tracked in ACT-6493. - -## Debugging - -- `GET /inspector/queue?limit=50` returns queue size and pending message metadata. -- `GET /inspector/summary` includes `queueSize` for quick queue health checks. -- `POST /queue/:name` with `wait: true` is useful to verify completable/request-response behavior. -- In non-dev mode, inspector endpoints require authorization. - -*/} - ## Recommendations - Actions are for getting data, queue entries are for mutating data. diff --git a/vendor/actors/docs/content/docs/quickstart/backend.mdx b/vendor/actors/docs/content/docs/quickstart/backend.mdx index 12c74b61..a4391cc4 100644 --- a/vendor/actors/docs/content/docs/quickstart/backend.mdx +++ b/vendor/actors/docs/content/docs/quickstart/backend.mdx @@ -27,7 +27,7 @@ npx skills add rivet-dev/skills ```sh -npm install rivetkit@next +npm install rivetkit ``` @@ -60,8 +60,6 @@ deno run --allow-net --allow-read --allow-env --watch index.ts Your server is now running on `http://localhost:6420`. Clients connect directly to the Rivet control plane on this port. -Visit [http://localhost:6420](http://localhost:6420) in your browser (or point your AI agent at it) to open the Rivet developer tools and inspect your actors live. - diff --git a/vendor/actors/docs/content/docs/quickstart/effect.mdx b/vendor/actors/docs/content/docs/quickstart/effect.mdx index ab89f27c..369319c7 100644 --- a/vendor/actors/docs/content/docs/quickstart/effect.mdx +++ b/vendor/actors/docs/content/docs/quickstart/effect.mdx @@ -18,7 +18,7 @@ Effect support is in beta. The `@rivetkit/effect` API may change between release Add `rivetkit`, the Effect SDK, and its Effect peers: ```sh -npm install rivetkit@next @rivetkit/effect@next effect @effect/platform-node +npm install rivetkit @rivetkit/effect effect @effect/platform-node ``` @@ -119,8 +119,6 @@ RIVET_RUN_ENGINE=1 npx tsx --watch src/main.ts Your server now connects to the Rivet control plane on `http://localhost:6420`. Clients connect directly to the control plane on this port. -Visit [http://localhost:6420](http://localhost:6420) in your browser (or point your AI agent at it) to open the Rivet developer tools and inspect your actors live. - To point at a remote engine instead, set `RIVET_ENDPOINT=https://...` and omit `RIVET_RUN_ENGINE`. diff --git a/vendor/actors/docs/content/docs/quickstart/next-js.mdx b/vendor/actors/docs/content/docs/quickstart/next-js.mdx deleted file mode 100644 index 58ac9250..00000000 --- a/vendor/actors/docs/content/docs/quickstart/next-js.mdx +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: "Next.js Quickstart" -description: "Connect a Next.js client component to Rivet Actors running in a separate node process." -skill: true ---- - -import { Hosting } from "@/components/docs/Hosting"; -import { InstallPackage } from "@/components/docs/InstallPackage"; - -Run your Rivet registry as a separate node process alongside Next.js. Client components connect to the control plane. - -## Quickstart - - - - -In your Next.js project, install the SDK and client integration: - - - - - - -Create the registry and a separate entry point under `src/rivet/`: - - - - - - - - - -Create `src/rivet/Counter.tsx` and render it from `src/app/page.tsx`: - - - - - - - - - -Start the node in one terminal, then your Next.js app in another: - -```sh -npx tsx --watch src/rivet/node.ts -``` - -```sh -npm run dev -``` - -Open your Next.js app and click **Increment**. Open `http://localhost:6420` to inspect the Actor in the local developer tools. - - - - -## Deploy - -Deploy the node as a long-running process. Set its private `RIVET_ENDPOINT` and your Next.js app's `NEXT_PUBLIC_RIVET_ENDPOINT` to the corresponding [production endpoints](/docs/connect). Keep the private token on the node. - - - -See the [React Client API Reference](/actors/docs/clients/react) for hooks and event subscriptions. diff --git a/vendor/actors/docs/content/docs/quickstart/react.mdx b/vendor/actors/docs/content/docs/quickstart/react.mdx index 0feeccce..4968113f 100644 --- a/vendor/actors/docs/content/docs/quickstart/react.mdx +++ b/vendor/actors/docs/content/docs/quickstart/react.mdx @@ -22,10 +22,28 @@ npx skills add rivet-dev/skills - + + +Create an empty project and install RivetKit, React, and Vite: ```sh -npm install rivetkit@next @rivetkit/react@next +mkdir my-app +cd my-app +npm init -y +npm pkg set type=module +npm install rivetkit @rivetkit/react react react-dom +npm install -D vite @vitejs/plugin-react tsx +``` + +The finished project has this layout: + +``` +my-app/ + backend/index.ts + frontend/Counter.tsx + frontend/main.tsx + index.html + vite.config.ts ``` @@ -34,18 +52,35 @@ npm install rivetkit@next @rivetkit/react@next Create your actor registry on the backend and start the server: - + -Set up your React application: +Create a component that connects to the actor, then mount it: - - + + + +Create the HTML page that loads it: + +```html index.html + + + + + Rivet Counter + + +
+ + + +``` + For detailed information about the React client API, see the [React Client API Reference](/actors/docs/clients/react).
@@ -98,8 +133,6 @@ npx vite Open `http://localhost:5173` in your browser. Try opening multiple tabs to see realtime sync in action. -Visit [http://localhost:6420](http://localhost:6420) in your browser (or point your AI agent at it) to open the Rivet developer tools and inspect your actors live. - diff --git a/vendor/actors/docs/content/docs/quickstart/rust.mdx b/vendor/actors/docs/content/docs/quickstart/rust.mdx index bb776989..f2e2d092 100644 --- a/vendor/actors/docs/content/docs/quickstart/rust.mdx +++ b/vendor/actors/docs/content/docs/quickstart/rust.mdx @@ -135,8 +135,6 @@ RIVETKIT_ENGINE_AUTO_DOWNLOAD=1 cargo run Your server now connects to the Rivet control plane on `http://localhost:6420`. Clients connect directly to the control plane on this port. -Visit [http://localhost:6420](http://localhost:6420) in your browser (or point your AI agent at it) to open the Rivet developer tools and inspect your actors live. - Already have a control plane binary? Set `RIVET_ENGINE_BINARY_PATH=/path/to/rivet-engine` to point at it instead. If you are working inside the [Rivet monorepo](https://github.com/rivet-dev/rivet), a local `cargo build -p rivet-engine` is discovered automatically from `target/debug`. @@ -163,7 +161,7 @@ use rivetkit::{ #[tokio::main] async fn main() -> Result<()> { - let client = Client::new(ClientConfig::new("http://localhost:6420").namespace("default")); + let client = Client::new(ClientConfig::new("http://localhost:6420")); let counter = client.get_or_create_typed_default::("counter", ["my-counter"])?; let count = counter.send(Increment { amount: 3 }).await?; diff --git a/vendor/actors/docs/content/docs/registry-configuration.mdx b/vendor/actors/docs/content/docs/registry-configuration.mdx index 16171a81..1e6953d4 100644 --- a/vendor/actors/docs/content/docs/registry-configuration.mdx +++ b/vendor/actors/docs/content/docs/registry-configuration.mdx @@ -31,7 +31,7 @@ After configuring your registry, start it: -`registry.start()` runs your process as a node. See [Architecture](/docs/architecture#actor-nodes). +`registry.start()` runs your process as a node. See [Architecture](/docs/architecture#nodes). ## Environment Variables diff --git a/vendor/actors/docs/content/docs/request-handler.mdx b/vendor/actors/docs/content/docs/request-handler.mdx index 8445071a..36f68c36 100644 --- a/vendor/actors/docs/content/docs/request-handler.mdx +++ b/vendor/actors/docs/content/docs/request-handler.mdx @@ -24,8 +24,6 @@ The `onRequest` handler processes HTTP requests sent to your actor. It receives
-See also the [raw fetch handler example](https://github.com/rivet-dev/rivet/tree/main/examples/raw-fetch-handler). - ## Streaming Responses & Server-Sent Events Return a `Response` with a `ReadableStream` body to stream data as it becomes available. For server-sent events (SSE), set `Content-Type` to `text/event-stream` and format each event as one or more fields followed by a blank line. diff --git a/vendor/actors/docs/content/docs/sqlite-profiling.mdx b/vendor/actors/docs/content/docs/sqlite-profiling.mdx index ce43f599..a829271c 100644 --- a/vendor/actors/docs/content/docs/sqlite-profiling.mdx +++ b/vendor/actors/docs/content/docs/sqlite-profiling.mdx @@ -44,7 +44,7 @@ For example, suppose a Prometheus result contains `fingerprint="select-a1b2c3d4e ## Query metrics -Collect [Prometheus metrics from each node](/docs/deploy/self-host/nodes/prometheus-metrics/) to use the queries below. +Collect [Prometheus metrics from each node](/docs/deploy/self-host/workers/prometheus-metrics/) to use the queries below. Some examples use optional metric families; see [Configure profiling](#configure-profiling). ### Slowest statements and transactions @@ -201,15 +201,66 @@ sum by (actor_name, type, byte_kind) ( ## Configure profiling -Profiling is enabled by default and most applications do not need to configure it. The entire profiling configuration surface is experimental and subject to change without notice. Set `profiling.slowOperationThresholdMs` or `profiling.baselineSampleRate` on the database provider when needed. +By default, native SQLite records metrics for all statement and transaction fingerprints, up to the tracking limits. Each query gets a duration histogram with 10 ms, 100 ms, and 1 s boundaries, outcome counters, and a counter for pages returned from storage. Duration `_count` and `_sum` provide execution count and cumulative duration. Worker queue depth, worker activity, transaction queue depth, fingerprint overflow, and dropped diagnostic events are also enabled. -Increase fingerprint limits only when `other` is hiding frequently repeated operations. Prometheus series remain allocated for the life of the process after admission. +All other profiling metric families are disabled by default. This configuration surface is experimental. + +For counters only, disable the duration histogram on your database provider: + +```ts +profiling: { + metrics: { durationHistogram: false }, +} +``` + +This emits `rivet_rivetkit_sqlite_operations_total` and `rivet_rivetkit_sqlite_duration_seconds_total` instead of the duration histogram. Outcome counters and `rivet_rivetkit_sqlite_pages_fetched_total` remain enabled. Disabled metric families allocate no series and receive no observations. + +To limit query metrics, set `filterQueries` (exact SQL) or `filterQueryFingerprints`. The filters are combined as a union; both empty or omitted means all queries. They do not suppress diagnostic logs or enabled actor-level storage metrics. + +```ts +profiling: { + filterQueries: ["SELECT value FROM items WHERE id = ?"], + durationHistogramBucketsSeconds: [0.01, 0.1, 1], + metrics: { localPages: true }, +} +``` + +`RIVETKIT_SQLITE_PROFILING` overrides the filters with a JSON object containing `filterQueries` and/or `filterQueryFingerprints`. `{}` selects all queries. The former `queries` and `fingerprints` fields have been removed. + +Duration bucket boundaries must be positive, finite, strictly increasing, and nonempty. All actor configurations enabling the duration histogram in one process must use the same boundaries; conflicting configurations are rejected. Other optional histograms retain their fixed boundaries. + +The `metrics` switches are: + +| Option | Default | Scope | +| --- | --- | --- | +| `duration` | `true` | Per-query count and cumulative duration | +| `durationHistogram` | `true` | Per-query duration buckets; requires `duration` | +| `outcomes` | `true` | Per-query counts by outcome, including errors | +| `pagesFetched` | `true` | Pages returned from storage per statement, including returned prefetch pages | +| `phaseDurationHistogram` | `false` | Per-query timing phases | +| `getPagesRoundTripsHistogram` | `false` | Storage round trips per operation | +| `transactionStatementCountHistogram` | `false` | Statements per transaction | +| `localPages` | `false` | Actor-level page counters by kind | +| `localBytes` | `false` | Actor-level byte counters by kind | +| `getPagesDurationHistogram` | `false` | Physical storage request duration | +| `getPagesPagesHistogram` | `false` | Pages per physical storage request | +| `getPagesResponseBytesHistogram` | `false` | Bytes per physical storage response | +| `getPagesMissingPages` | `false` | Missing response pages | +| `workerQueueDepth` | `true` | Actor-level queued SQLite work | +| `workerInflight` | `true` | Actor-level executing SQLite work | +| `coordinatorQueueDepth` | `true` | Actor-level transaction waiters | +| `fingerprintOverflow` | `true` | Observations exceeding tracking limits | +| `eventDropped` | `true` | Dropped diagnostic events | + +The default limits are 512 statement fingerprints, 8 transaction fingerprints, and 25,000 profiling series per process. Series budgeting accounts for enabled metric families and configured duration buckets. Prometheus series remain allocated for the lifetime of the process. Increase limits only for useful operations that repeat regularly. + +`slowOperationThresholdMs`, `baselineSampleRate`, and diagnostic event limits control logs, independently of metric selection. Sampling logs does not sample Prometheus observations. ## Troubleshooting -### Most results are `other` +### Queries are missing -Fast statements initially appear under `other`, while overflow metrics show when a fingerprint limit was reached. Increase limits only for useful operations that repeat regularly. +Check the query filters and `rivet_rivetkit_sqlite_fingerprint_overflow_total`. Once a fingerprint or series limit is reached, new per-query observations are dropped rather than creating unbounded series. Enable the optional metric families needed by the examples above. ### Too many fingerprints @@ -229,4 +280,4 @@ Diagnostic events are sampled and bounded. Check `rivet_rivetkit_sqlite_event_dr ### No profiling metrics appear -Confirm profiling was not disabled in the database provider. Profiling currently applies to native actor-local SQLite, not remote or wasm SQLite. +Confirm the relevant metric family is enabled and the query matches your filters. Profiling currently applies to native actor-local SQLite, not remote or wasm SQLite. diff --git a/vendor/actors/docs/content/docs/sqlite.mdx b/vendor/actors/docs/content/docs/sqlite.mdx index 1fe19c21..59d1718b 100644 --- a/vendor/actors/docs/content/docs/sqlite.mdx +++ b/vendor/actors/docs/content/docs/sqlite.mdx @@ -117,19 +117,6 @@ It's recommended to use queues for mutations and actions for read-only queries. -{/* TODO(code): restore when the control plane exposes an API to read an Actor's inspector token. Tracked in ACT-6493. - -## Debugging - -- `GET /inspector/summary` includes `isDatabaseEnabled` so you can confirm SQLite is configured. -- `GET /inspector/database/schema` returns the tables and views discovered in the actor's SQLite database. -- `GET /inspector/database/rows?table=...&limit=100&offset=0` returns paged rows for a specific table or view. -- `POST /inspector/database/execute` lets you run ad-hoc SQL for debugging and data fixes with positional `args` or named `properties`. -- Keep a small read-only action for quick query verification while debugging. -- In non-dev mode, inspector endpoints require authorization. - -*/} - ## Profiling See [SQLite Profiling](/actors/docs/sqlite-profiling) to understand query fingerprints, transaction names, metrics, and diagnostics. diff --git a/vendor/actors/docs/content/docs/state.mdx b/vendor/actors/docs/content/docs/state.mdx index 62ad5454..871c0fd7 100644 --- a/vendor/actors/docs/content/docs/state.mdx +++ b/vendor/actors/docs/content/docs/state.mdx @@ -285,9 +285,3 @@ For the full query API, schema migrations, transactions, and the Drizzle ORM, se - [SQLite](/actors/docs/sqlite): raw SQL against the embedded per-actor database. - [SQLite + Drizzle](/actors/docs/sqlite-drizzle): typed schema and query APIs. - -## Debugging - -- `GET /inspector/state` returns the actor's current state and `isStateEnabled`. -- `PATCH /inspector/state` lets you set state directly while debugging. -- In non-dev mode, inspector endpoints require authorization. diff --git a/vendor/actors/docs/content/docs/troubleshooting.mdx b/vendor/actors/docs/content/docs/troubleshooting.mdx new file mode 100644 index 00000000..313d57f2 --- /dev/null +++ b/vendor/actors/docs/content/docs/troubleshooting.mdx @@ -0,0 +1,71 @@ +--- +title: "Troubleshooting" +description: "Diagnose common Rivet Actors setup, connection, deployment, and runtime problems with targeted checks and corrective steps." +skill: true +--- + +## Common Steps + +Before diving into specific errors, try these general troubleshooting steps: + +- Check your server logs for `level=ERROR` or `level=WARN` messages. +- Check if any of your backend processes have crashed or restarted unexpectedly. +- If you need more diagnostics, set `RIVET_LOG_LEVEL=DEBUG` for verbose logging. See [Logging](/actors/docs/logging) for more options. + +## Reporting Issues + +If you're stuck, reach out on [Discord](https://rivet.dev/discord) or file an issue on [GitHub](https://github.com/rivet-dev/rivet/issues). + +When reporting, please include: + +- **Symptoms** + - Whether this is happening in local dev, deployed, or both + - The error you're seeing (screenshot or error message) + - Relevant source code related to the issue +- **What you've tried to solve it** +- **Environment** + - RivetKit version + - Runtime (Node, Bun, etc.) including version + - If applicable, hosting platform in use (e.g. Kubernetes, Railway, AWS ECS) + - If applicable, HTTP router in use (e.g. Hono, Express, Elysia) + +## Actor status is crashed + +See [Actor Statuses](/docs/statuses) for more about this status. + +The dashboard will show the specific failure reason. Common errors include: + +### `crashed` + +The actor's `run` handler threw an unhandled exception or exited unexpectedly. Check your actor logs for the error message and stack trace. + +{/* TODO(code): list the allocation failure reasons the control plane reports for a Rivet Actor once it records them. Today only a crash in your own code is reported. */} + +### `internal_error` + +An unexpected error occurred within Rivet. If this persists, please [contact support](https://rivet.dev/actors/docs). + +## Actors crashing immediately on startup + +If your actors are being created and then immediately destroyed or crashing, there is likely an error being thrown in your `createState` or `onCreate` lifecycle hooks. These hooks run during actor initialization before the actor is marked as ready. + +Check your server logs for the error message and stack trace. Common causes include: + +- An exception thrown in `createState` (e.g. invalid input, failed validation, or a runtime error when computing initial state) +- An exception thrown in `onCreate` (e.g. a failing external API call, missing configuration, or invalid setup logic) + +Fix the error in the relevant lifecycle hook and redeploy. + +## Actors not upgrading to new code + +During a rollout, old and new nodes both run Rivet Actors until the old nodes stop. A Rivet Actor started on an old node keeps running the old code until it sleeps or its node stops. Finish the rollout by stopping every old node. See [Versions & Upgrades](/docs/versions). + +## Actor status is pending + +See [Actor Statuses](/docs/statuses) for more about this status. + +An actor stays in "pending" status while no node in its node pool is connected to accept it. + +- Check that at least one node is running and that its `RIVET_ENDPOINT` points at the right control plane and namespace. +- Check that the node joined the node pool the actor runs in. A node joins the pool named by `RIVET_POOL`, or `default`. +- Check your node logs for connection errors. diff --git a/vendor/actors/docs/content/docs/websocket-handler.mdx b/vendor/actors/docs/content/docs/websocket-handler.mdx index 61a0cb04..fcbec4cf 100644 --- a/vendor/actors/docs/content/docs/websocket-handler.mdx +++ b/vendor/actors/docs/content/docs/websocket-handler.mdx @@ -172,8 +172,6 @@ You can proxy WebSocket connections from your own server to actor handlers using -See also the [raw WebSocket handler with proxy example](https://github.com/rivet-dev/rivet/tree/main/examples/raw-websocket-handler-proxy). - ## Connection & Lifecycle Hooks `onWebSocket` will trigger the `onBeforeConnect`, `onConnect`, and `onDisconnect` hooks. Read more about [lifecycle hooks](/actors/docs/lifecycle). diff --git a/vendor/actors/docs/content/guides/ai-agent.mdx b/vendor/actors/docs/content/guides/ai-agent.mdx new file mode 100644 index 00000000..8049ffeb --- /dev/null +++ b/vendor/actors/docs/content/guides/ai-agent.mdx @@ -0,0 +1,133 @@ +--- +title: "AI Agent" +description: "Build an AI agent backend with persistent memory: one Rivet Actor per conversation, queued message handling, and streaming LLM responses as realtime events." +templates: ["ai-agent"] +--- + +Patterns for building AI agent backends with RivetKit, where each conversation is one Rivet Actor that owns its memory, its message queue, and its streaming output. + +## Starter Code + +Start with one of the working examples on [GitHub](https://github.com/rivet-dev/rivet/tree/main/examples/ai-agent) and adapt it. The sections below describe the flagship `ai-agent` example unless a variant is called out explicitly. + +| Variant | Starter Code | Use When | +| --- | --- | --- | +| Queue-driven AI SDK agent | [GitHub](https://github.com/rivet-dev/rivet/tree/main/examples/ai-agent) | You want a streaming chat agent where each conversation keeps its own persistent memory and processes one message at a time. | +| Sandbox coding agent | [GitHub](https://github.com/rivet-dev/rivet/tree/main/examples/sandbox-coding-agent) | The agent should run a coding agent (Codex by default) inside an isolated [sandbox](/agentos/docs) via Docker, Daytona, or E2B. | +| Durable streams agent (experimental) | [GitHub](https://github.com/rivet-dev/rivet/tree/main/examples/experimental-durable-streams-ai-agent) | You want replayable, restart-safe prompt and response delivery through durable streams instead of actor state and events. | + +## Conversation Memory + +Use one actor per conversation, keyed by a conversation or agent id (see [Actor Keys](/actors/docs/keys)). The agent actor's persistent [state](/actors/docs/state) is the conversation memory: in the `ai-agent` example, `messages` and `status` live in JSON actor state and survive sleep and restarts with no external database. Every model call rebuilds the prompt from `c.state.messages` plus a system prompt, so memory and inference input are the same data. + +| Variant | Where Memory Lives | Persisted State Fields | +| --- | --- | --- | +| `ai-agent` | JSON actor state | `messages`, `status` | +| `sandbox-coding-agent` | JSON actor state plus the sandbox ACP session | `messages`, `status`, `sessionId` | +| `experimental-durable-streams-ai-agent` | Durable streams; the actor stores only its conversation id and a read cursor | `conversationId`, `promptStreamOffset` | + +## Message Handling + +In the `ai-agent` example, the client pushes user input onto the agent's `message` [queue](/actors/docs/queues) with `agent.connection.send("message", { text, sender })`. This is a queue push, not an action call. The actor's `run` hook (see [Lifecycle](/actors/docs/lifecycle)) consumes the queue serially with `for await (const queued of c.queue.iter())`. + +Serial queue consumption is the per-conversation concurrency guarantee: at most one in-flight model call per actor, with no extra locking. The `status` field (`thinking` while a model call is in flight) is UI signal only; the run loop is the actual lock. The loop also checks `c.aborted` inside the token stream so shutdown exits gracefully. + +| Variant | Message Ingress | Serialization Guarantee | +| --- | --- | --- | +| `ai-agent` | `message` queue pushed via `connection.send` | `run` hook pops one queued message at a time with `c.queue.iter()`. | +| `sandbox-coding-agent` | `sendMessage` [action](/actors/docs/actions), no queue | Each call awaits the sandbox round trip before broadcasting the result. | +| `experimental-durable-streams-ai-agent` | Durable prompt stream long-polled from `onWake` | `promptStreamOffset` is persisted per chunk, so restarts resume without reprocessing prompts. | + +## Streaming Responses + +The `ai-agent` actor broadcasts a `response` [event](/actors/docs/events) for every model text delta. The payload carries `messageId`, the per-token `delta`, the cumulative `content`, and a `done` flag (plus `error` on failure), so clients can either append deltas or idempotently replace the message by `messageId` using `content`. The example frontend replaces by `messageId`, which tolerates dropped events. The terminal broadcast has an empty `delta`, the full `content`, and `done: true`. + +Because the assistant message object lives in `c.state.messages` and is mutated in place during streaming, partial content persists if the actor restarts mid-stream. The example broadcasts once per AI SDK delta with no throttling; batching or throttling deltas is a recommended extension for high-traffic deployments, not something the example implements. + +Variant differences: `sandbox-coding-agent` sends a single `response` broadcast with `done: true` after the sandbox finishes (no incremental streaming), and `experimental-durable-streams-ai-agent` appends per-token chunks to a durable response stream, then broadcasts `responseComplete` or `responseError`. + +## Architecture + +| Topic | Summary | +| --- | --- | +| Topology | `agentManager["primary"]` singleton directory plus one `agent[agentId]` actor per conversation. | +| Ingress | Client pushes `AgentQueueMessage` payloads onto the agent's `message` queue with `connection.send`. | +| Streaming | One `response` broadcast per model delta, terminal broadcast with `done: true`. | +| Memory | Full transcript and status in JSON actor state; no external database. | + +The manager creates `AgentInfo` records and warms each agent through [actor-to-actor communication](/actors/docs/communicating-between-actors): `createAgent` calls `c.client()`, then `client.agent.getOrCreate([info.id])` and awaits `getStatus()` so the conversation actor exists before the client connects. The sandbox variant extends this topology with a `codingSandbox` actor that shares the agent's key (`codingSandbox.getOrCreate([c.key[0]])`), so the agent-to-sandbox mapping is implicit in the key space. + +**Actors** + + + + +- **Key**: `agentManager["primary"]` +- **Responsibility**: Directory actor. Creates `AgentInfo` records, lists agents, and warms each agent actor via `c.client()`. +- **Actions** + - `createAgent` + - `listAgents` +- **Queues** + - None +- **State** + - JSON + - `agents` + + + + +- **Key**: `agent[agentId]` +- **Responsibility**: One actor per conversation. Holds the full message history and status, consumes queued user messages in its `run` loop, calls the model via the AI SDK, and broadcasts streaming deltas. +- **Actions** + - `getHistory` + - `getStatus` +- **Queues** + - `message` +- **Events** + - `messageAdded` + - `status` + - `response` +- **State** + - JSON + - `messages` + - `status` + + + + +**Lifecycle** + +```mermaid +sequenceDiagram + participant C as Client + participant AM as agentManager + participant A as agent + participant LLM as Model API + + C->>AM: createAgent(name) + AM->>A: getOrCreate([info.id]) + getStatus() + AM-->>C: AgentInfo + C->>A: connection.send("message", {text, sender}) + Note over A: run loop pops queue via c.queue.iter() + A-->>C: messageAdded (user message) + A-->>C: messageAdded (assistant placeholder) + A-->>C: status (thinking) + A->>LLM: streamText(system prompt + history) + loop each text delta + LLM-->>A: delta + A-->>C: response {messageId, delta, content, done: false} + end + A-->>C: response {delta: "", content, done: true} + A-->>C: status (idle) +``` + +## Security Checklist + +The examples ship without auth so they stay minimal. Apply this baseline before exposing an agent backend. + +- **API keys stay server-side**: `OPENAI_API_KEY` (or `ANTHROPIC_API_KEY`) is read by the AI SDK inside the actor process. The key never reaches the browser; clients only talk to the actor over RivetKit. The sandbox variant forwards keys into the sandbox env, never to the client. +- **Add authentication**: The examples have no auth, so anyone who reaches the server can create agents, list them, and message any agent whose key they can guess. Add `onBeforeConnect` or `createConnState` checks with scoped tokens as a recommended extension. See [Authentication](/actors/docs/authentication). +- **Validate and rate-limit queue payloads**: The example only skips bodies without a string `text`. Enforce payload size limits, schema validation, and per-connection rate limits as a recommended extension. +- **Derive sender identity server-side**: The example trusts the client-supplied `sender` field verbatim. Bind sender identity to the authenticated connection instead. +- **Cap or trim message history**: The example sends the full transcript on every model call with no cap. Trim or summarize old messages as a recommended extension so prompts and state stay bounded. +- **Set cost ceilings per conversation**: Add per-agent token budgets and quotas as a recommended extension. The sandbox variant runs real compute, so also enforce per-user sandbox quotas and restrict sandbox network egress. diff --git a/vendor/actors/docs/content/guides/arena-game.mdx b/vendor/actors/docs/content/guides/arena-game.mdx index c99d3134..dcc7e89f 100644 --- a/vendor/actors/docs/content/guides/arena-game.mdx +++ b/vendor/actors/docs/content/guides/arena-game.mdx @@ -41,7 +41,7 @@ What we'll build: ```sh -npm add rivetkit@next +npm add rivetkit ``` diff --git a/vendor/actors/docs/content/guides/authentication.mdx b/vendor/actors/docs/content/guides/authentication.mdx index df2394b6..45adb018 100644 --- a/vendor/actors/docs/content/guides/authentication.mdx +++ b/vendor/actors/docs/content/guides/authentication.mdx @@ -39,7 +39,7 @@ What we'll build: ```sh -npm add rivetkit@next hono +npm add rivetkit hono ``` diff --git a/vendor/actors/docs/content/guides/battle-royale.mdx b/vendor/actors/docs/content/guides/battle-royale.mdx index 84e99e8b..133c1ef2 100644 --- a/vendor/actors/docs/content/guides/battle-royale.mdx +++ b/vendor/actors/docs/content/guides/battle-royale.mdx @@ -41,7 +41,7 @@ What we'll build: ```sh -npm add rivetkit@next +npm add rivetkit ``` diff --git a/vendor/actors/docs/content/guides/chat-room.mdx b/vendor/actors/docs/content/guides/chat-room.mdx index 1b399eb2..fa7bced7 100644 --- a/vendor/actors/docs/content/guides/chat-room.mdx +++ b/vendor/actors/docs/content/guides/chat-room.mdx @@ -41,7 +41,7 @@ What we'll build: ```sh -npm add rivetkit@next @rivetkit/react@next +npm add rivetkit @rivetkit/react ``` diff --git a/vendor/actors/docs/content/guides/collaborative-text-editor-ot.mdx b/vendor/actors/docs/content/guides/collaborative-text-editor-ot.mdx index 18e70694..bd347d36 100644 --- a/vendor/actors/docs/content/guides/collaborative-text-editor-ot.mdx +++ b/vendor/actors/docs/content/guides/collaborative-text-editor-ot.mdx @@ -44,7 +44,7 @@ This guide uses OT. The other approach is a CRDT, where every client can merge e ```sh -npm add rivetkit@next @rivetkit/react@next +npm add rivetkit @rivetkit/react ``` The OT code is part of the example, so there is no OT package to install. diff --git a/vendor/actors/docs/content/guides/collaborative-text-editor.mdx b/vendor/actors/docs/content/guides/collaborative-text-editor.mdx index 5e013387..708124ff 100644 --- a/vendor/actors/docs/content/guides/collaborative-text-editor.mdx +++ b/vendor/actors/docs/content/guides/collaborative-text-editor.mdx @@ -45,7 +45,7 @@ This guide uses a CRDT. Yjs merges edits in any order on any client, so the serv ```sh -npm add rivetkit@next @rivetkit/react@next yjs y-protocols +npm add rivetkit @rivetkit/react yjs y-protocols ``` diff --git a/vendor/actors/docs/content/guides/cron-jobs.mdx b/vendor/actors/docs/content/guides/cron-jobs.mdx index 5e481fb8..c4468eaf 100644 --- a/vendor/actors/docs/content/guides/cron-jobs.mdx +++ b/vendor/actors/docs/content/guides/cron-jobs.mdx @@ -43,7 +43,7 @@ What we'll build: ```sh -npm add rivetkit@next @rivetkit/react@next +npm add rivetkit @rivetkit/react ``` diff --git a/vendor/actors/docs/content/guides/idle-game.mdx b/vendor/actors/docs/content/guides/idle-game.mdx index 40b07ee4..eebc57a4 100644 --- a/vendor/actors/docs/content/guides/idle-game.mdx +++ b/vendor/actors/docs/content/guides/idle-game.mdx @@ -39,7 +39,7 @@ What we'll build: ```sh -npm add rivetkit@next +npm add rivetkit ``` diff --git a/vendor/actors/docs/content/guides/io-game.mdx b/vendor/actors/docs/content/guides/io-game.mdx index e682cc69..46f7c422 100644 --- a/vendor/actors/docs/content/guides/io-game.mdx +++ b/vendor/actors/docs/content/guides/io-game.mdx @@ -41,7 +41,7 @@ What we'll build: ```sh -npm add rivetkit@next +npm add rivetkit ``` diff --git a/vendor/actors/docs/content/guides/live-cursors.mdx b/vendor/actors/docs/content/guides/live-cursors.mdx index f16ff435..f0a6cbff 100644 --- a/vendor/actors/docs/content/guides/live-cursors.mdx +++ b/vendor/actors/docs/content/guides/live-cursors.mdx @@ -39,7 +39,7 @@ What we'll build: ```sh -npm add rivetkit@next @rivetkit/react@next +npm add rivetkit @rivetkit/react ``` diff --git a/vendor/actors/docs/content/guides/open-world-game.mdx b/vendor/actors/docs/content/guides/open-world-game.mdx index 3f9bebdd..aa2b903f 100644 --- a/vendor/actors/docs/content/guides/open-world-game.mdx +++ b/vendor/actors/docs/content/guides/open-world-game.mdx @@ -39,7 +39,7 @@ What we'll build: ```sh -npm add rivetkit@next +npm add rivetkit ``` diff --git a/vendor/actors/docs/content/guides/party-game.mdx b/vendor/actors/docs/content/guides/party-game.mdx index cc971f18..aa137e39 100644 --- a/vendor/actors/docs/content/guides/party-game.mdx +++ b/vendor/actors/docs/content/guides/party-game.mdx @@ -41,7 +41,7 @@ What we'll build: ```sh -npm add rivetkit@next +npm add rivetkit ``` diff --git a/vendor/actors/docs/content/guides/per-tenant-database.mdx b/vendor/actors/docs/content/guides/per-tenant-database.mdx index 183943ea..093ebe3e 100644 --- a/vendor/actors/docs/content/guides/per-tenant-database.mdx +++ b/vendor/actors/docs/content/guides/per-tenant-database.mdx @@ -43,7 +43,7 @@ What we'll build: ```sh -npm add rivetkit@next @rivetkit/react@next +npm add rivetkit @rivetkit/react ``` diff --git a/vendor/actors/docs/content/guides/physics-2d-game.mdx b/vendor/actors/docs/content/guides/physics-2d-game.mdx index 54db48c2..02ee3f76 100644 --- a/vendor/actors/docs/content/guides/physics-2d-game.mdx +++ b/vendor/actors/docs/content/guides/physics-2d-game.mdx @@ -38,7 +38,7 @@ What we'll build: ```sh -npm add rivetkit@next @dimforge/rapier2d-compat +npm add rivetkit @dimforge/rapier2d-compat ``` diff --git a/vendor/actors/docs/content/guides/physics-3d-game.mdx b/vendor/actors/docs/content/guides/physics-3d-game.mdx index babec4f8..ba3f37eb 100644 --- a/vendor/actors/docs/content/guides/physics-3d-game.mdx +++ b/vendor/actors/docs/content/guides/physics-3d-game.mdx @@ -38,7 +38,7 @@ What we'll build: ```sh -npm add rivetkit@next @dimforge/rapier3d-compat three +npm add rivetkit @dimforge/rapier3d-compat three ``` diff --git a/vendor/actors/docs/content/guides/ranked-game.mdx b/vendor/actors/docs/content/guides/ranked-game.mdx index cc9e5484..7ef827d4 100644 --- a/vendor/actors/docs/content/guides/ranked-game.mdx +++ b/vendor/actors/docs/content/guides/ranked-game.mdx @@ -42,7 +42,7 @@ What we'll build: ```sh -npm add rivetkit@next +npm add rivetkit ``` diff --git a/vendor/actors/docs/content/guides/turn-based-game.mdx b/vendor/actors/docs/content/guides/turn-based-game.mdx index 4764b8c1..d4e11d25 100644 --- a/vendor/actors/docs/content/guides/turn-based-game.mdx +++ b/vendor/actors/docs/content/guides/turn-based-game.mdx @@ -38,7 +38,7 @@ What we'll build: ```sh -npm add rivetkit@next +npm add rivetkit ``` diff --git a/vendor/actors/docs/sidebar.json b/vendor/actors/docs/sidebar.json index 70be1662..0be73cdb 100644 --- a/vendor/actors/docs/sidebar.json +++ b/vendor/actors/docs/sidebar.json @@ -23,11 +23,6 @@ "href": "/actors/docs/quickstart/react", "icon": "faReact" }, - { - "title": "Next.js", - "href": "/actors/docs/quickstart/next-js", - "icon": "faNextjs" - }, { "title": "Rust", "href": "/actors/docs/quickstart/rust", @@ -94,6 +89,10 @@ "title": "Communication & Networking", "collapsible": true, "pages": [ + { + "title": "Authentication", + "href": "/actors/docs/authentication" + }, { "title": "Connections", "href": "/actors/docs/connections" @@ -120,10 +119,6 @@ "title": "Lifecycle", "href": "/actors/docs/lifecycle" }, - { - "title": "Permissions", - "href": "/actors/docs/permissions" - }, { "title": "Input Parameters", "href": "/actors/docs/input" @@ -163,7 +158,7 @@ "href": "/actors/docs/logging" }, { - "title": "Performance Monitoring & Tuning", + "title": "Performance Monitoring", "href": "/actors/docs/performance-monitoring" }, { @@ -246,6 +241,10 @@ { "title": "Reference", "pages": [ + { + "title": "Troubleshooting", + "href": "/actors/docs/troubleshooting" + }, { "title": "Production Checklist", "href": "/actors/docs/production-checklist" @@ -267,7 +266,7 @@ "href": "/actors/docs/http-server" }, { - "title": "Runtime Environment Variables", + "title": "Environment Variables", "href": "/actors/docs/environment-variables" }, { @@ -281,15 +280,11 @@ ], "guides": [ { - "title": "Architecture", + "title": "Agents", "pages": [ { - "title": "A Radically Simpler Architecture", - "href": "/guides/a-radically-simpler-architecture" - }, - { - "title": "Authenticate Users End to End", - "href": "/guides/authentication" + "title": "AI Agent", + "href": "/guides/ai-agent" } ] }, @@ -376,6 +371,19 @@ "href": "/guides/collaborative-text-editor-ot" } ] + }, + { + "title": "Concepts", + "pages": [ + { + "title": "A Radically Simpler Architecture", + "href": "/guides/a-radically-simpler-architecture" + }, + { + "title": "Authentication", + "href": "/guides/authentication" + } + ] } ] } diff --git a/vendor/actors/examples/chat-room/tests/chat-room.test.ts b/vendor/actors/examples/chat-room/tests/chat-room.test.ts deleted file mode 100644 index f070920e..00000000 --- a/vendor/actors/examples/chat-room/tests/chat-room.test.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { setupTest } from "rivetkit/test"; -import { expect, test } from "vitest"; -import { registry } from "../src/index.ts"; - -test("Chat room can handle message sending and history", async (ctx) => { - const { client } = await setupTest(ctx, registry); - const room = client.chatRoom.getOrCreate(["test-room"]); - - // Test initial state - const initialHistory = await room.getHistory(); - expect(initialHistory).toEqual([]); - - // Send a message - const message1 = await room.sendMessage("Alice", "Hello everyone!"); - - // Verify message structure - expect(message1).toMatchObject({ - sender: "Alice", - text: "Hello everyone!", - timestamp: expect.any(Number), - }); - - // Send another message - const message2 = await room.sendMessage("Bob", "Hi Alice!"); - - // Verify messages are stored in order - const history = await room.getHistory(); - expect(history).toHaveLength(2); - expect(history[0]).toEqual(message1); - expect(history[1]).toEqual(message2); -}); - -test("Chat room message timestamps are sequential", async (ctx) => { - const { client } = await setupTest(ctx, registry); - const room = client.chatRoom.getOrCreate(["test-timestamps"]); - - const message1 = await room.sendMessage("User1", "First message"); - const message2 = await room.sendMessage("User2", "Second message"); - const message3 = await room.sendMessage("User1", "Third message"); - - expect(message2.timestamp).toBeGreaterThanOrEqual(message1.timestamp); - expect(message3.timestamp).toBeGreaterThanOrEqual(message2.timestamp); - - const history = await room.getHistory(); - for (let i = 1; i < history.length; i++) { - expect(history[i].timestamp).toBeGreaterThanOrEqual( - history[i - 1].timestamp, - ); - } -}); - -test("Chat room supports multiple users", async (ctx) => { - const { client } = await setupTest(ctx, registry); - const room = client.chatRoom.getOrCreate(["test-multiuser"]); - - // Multiple users sending messages - await room.sendMessage("Alice", "Hello!"); - await room.sendMessage("Bob", "Hey there!"); - await room.sendMessage("Charlie", "Good morning!"); - await room.sendMessage("Alice", "How is everyone?"); - - const history = await room.getHistory(); - expect(history).toHaveLength(4); - - // Verify senders - expect(history[0].sender).toBe("Alice"); - expect(history[1].sender).toBe("Bob"); - expect(history[2].sender).toBe("Charlie"); - expect(history[3].sender).toBe("Alice"); - - // Verify message content - expect(history[0].text).toBe("Hello!"); - expect(history[1].text).toBe("Hey there!"); - expect(history[2].text).toBe("Good morning!"); - expect(history[3].text).toBe("How is everyone?"); -}); - -test("Chat room handles empty messages", async (ctx) => { - const { client } = await setupTest(ctx, registry); - const room = client.chatRoom.getOrCreate(["test-empty"]); - - // Test empty message - const emptyMessage = await room.sendMessage("User", ""); - expect(emptyMessage.text).toBe(""); - expect(emptyMessage.sender).toBe("User"); - expect(emptyMessage.timestamp).toBeGreaterThan(0); - - const history = await room.getHistory(); - expect(history).toHaveLength(1); - expect(history[0]).toEqual(emptyMessage); -}); diff --git a/vendor/actors/examples/chat-room/vitest.config.ts b/vendor/actors/examples/chat-room/vitest.config.ts deleted file mode 100644 index f913a97a..00000000 --- a/vendor/actors/examples/chat-room/vitest.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { defineConfig } from "vitest/config"; - -export default defineConfig({ - server: { - port: 5173, - }, - test: { - include: ["tests/**/*.test.ts"], - }, -}); diff --git a/vendor/actors/examples/collaborative-document-ot/package.json b/vendor/actors/examples/collaborative-document-ot/package.json index 6a1b6b9c..0f62034c 100644 --- a/vendor/actors/examples/collaborative-document-ot/package.json +++ b/vendor/actors/examples/collaborative-document-ot/package.json @@ -23,10 +23,10 @@ "vitest": "^3.1.1" }, "dependencies": { - "@rivetkit/react": "^2.3.31", + "@rivetkit/react": "^3.0.1", "react": "^18.2.0", "react-dom": "^18.2.0", - "rivetkit": "^2.3.31" + "rivetkit": "^3.0.1" }, "stableVersion": "0.8.0", "license": "MIT" diff --git a/vendor/actors/examples/collaborative-document-ot/tests/collaborative-document-ot.test.ts b/vendor/actors/examples/collaborative-document-ot/tests/collaborative-document-ot.test.ts deleted file mode 100644 index 4234ecad..00000000 --- a/vendor/actors/examples/collaborative-document-ot/tests/collaborative-document-ot.test.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { setupTest } from "rivetkit/test"; -import { describe, expect, test } from "vitest"; -import { registry } from "../src/index.ts"; -import { apply, diff, type Operation, transform } from "../src/ot.ts"; - -describe("transform", () => { - test("concurrent inserts at the same position converge", () => { - const base = "hello"; - const a: Operation = [{ retain: 5 }, { insert: " world" }]; - const b: Operation = [{ retain: 5 }, { insert: "!" }]; - const [a2, b2] = transform(a, b); - expect(apply(apply(base, a), b2)).toBe("hello world!"); - expect(apply(apply(base, b), a2)).toBe("hello world!"); - }); - - test("an insert inside a concurrent delete survives", () => { - const base = "abcdef"; - const del = diff(base, "af"); - const ins = diff(base, "abcXdef"); - const [del2, ins2] = transform(del, ins); - expect(apply(apply(base, del), ins2)).toBe("aXf"); - expect(apply(apply(base, ins), del2)).toBe("aXf"); - }); - - test("random concurrent edits converge", () => { - const alphabet = "abcxyz "; - const randomText = (length: number) => - Array.from( - { length }, - () => alphabet[Math.floor(Math.random() * alphabet.length)], - ).join(""); - const randomEdit = (text: string) => { - const start = Math.floor(Math.random() * (text.length + 1)); - const end = - start + Math.floor(Math.random() * (text.length - start + 1)); - return ( - text.slice(0, start) + - randomText(Math.floor(Math.random() * 4)) + - text.slice(end) - ); - }; - - for (let i = 0; i < 500; i++) { - const base = randomText(Math.floor(Math.random() * 12)); - const a = diff(base, randomEdit(base)); - const b = diff(base, randomEdit(base)); - const [a2, b2] = transform(a, b); - expect(apply(apply(base, a), b2)).toBe(apply(apply(base, b), a2)); - } - }); -}); - -describe("document actor", () => { - test("transforms operations based on an old revision", async (ctx) => { - const { client } = await setupTest(ctx, registry); - const doc = client.document.getOrCreate([ - `test-concurrent-${crypto.randomUUID()}`, - ]); - - await doc.submitOperation("setup", 0, [{ insert: "hello" }]); - const base = await doc.getSnapshot(); - expect(base).toEqual({ text: "hello", revision: 1 }); - - // Both clients edit revision 1 without seeing each other's edit. - const [first, second] = await Promise.all([ - doc.submitOperation("alice", 1, diff("hello", "hello world")), - doc.submitOperation("bob", 1, diff("hello", "Oh, hello")), - ]); - expect([first, second].sort()).toEqual([2, 3]); - - const snapshot = await doc.getSnapshot(); - expect(snapshot).toEqual({ text: "Oh, hello world", revision: 3 }); - }); - - test("rejects a revision from the future", async (ctx) => { - const { client } = await setupTest(ctx, registry); - const doc = client.document.getOrCreate([ - `test-future-${crypto.randomUUID()}`, - ]); - await expect( - doc.submitOperation("alice", 5, [{ insert: "x" }]), - ).rejects.toThrow("unknown base revision"); - }); -}); diff --git a/vendor/actors/examples/collaborative-document-ot/vitest.config.ts b/vendor/actors/examples/collaborative-document-ot/vitest.config.ts deleted file mode 100644 index f913a97a..00000000 --- a/vendor/actors/examples/collaborative-document-ot/vitest.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { defineConfig } from "vitest/config"; - -export default defineConfig({ - server: { - port: 5173, - }, - test: { - include: ["tests/**/*.test.ts"], - }, -}); diff --git a/vendor/actors/examples/collaborative-document/package.json b/vendor/actors/examples/collaborative-document/package.json index a6a9530d..bdbfc750 100644 --- a/vendor/actors/examples/collaborative-document/package.json +++ b/vendor/actors/examples/collaborative-document/package.json @@ -23,10 +23,10 @@ "vitest": "^3.1.1" }, "dependencies": { - "@rivetkit/react": "^2.3.31", + "@rivetkit/react": "^3.0.1", "react": "^18.2.0", "react-dom": "^18.2.0", - "rivetkit": "^2.3.31", + "rivetkit": "^3.0.1", "y-protocols": "^1.0.6", "yjs": "^13.6.24" }, diff --git a/vendor/actors/examples/cursors/package.json b/vendor/actors/examples/cursors/package.json index 226bc3b6..bc6c9fa0 100644 --- a/vendor/actors/examples/cursors/package.json +++ b/vendor/actors/examples/cursors/package.json @@ -23,11 +23,11 @@ "vitest": "^3.1.1" }, "dependencies": { - "@rivetkit/react": "^2.3.31", + "@rivetkit/react": "^3.0.1", "react": "^18.2.0", "react-dom": "^18.2.0", - "rivetkit": "^2.3.31" + "rivetkit": "^3.0.1" }, "stableVersion": "0.8.0", "license": "MIT" -} \ No newline at end of file +} diff --git a/vendor/actors/examples/cursors/vitest.config.ts b/vendor/actors/examples/cursors/vitest.config.ts deleted file mode 100644 index f913a97a..00000000 --- a/vendor/actors/examples/cursors/vitest.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { defineConfig } from "vitest/config"; - -export default defineConfig({ - server: { - port: 5173, - }, - test: { - include: ["tests/**/*.test.ts"], - }, -}); diff --git a/vendor/actors/examples/docs/actors-quickstart-next-js/app/page.tsx b/vendor/actors/examples/docs/actors-quickstart-next-js/app/page.tsx deleted file mode 100644 index a0c8ade1..00000000 --- a/vendor/actors/examples/docs/actors-quickstart-next-js/app/page.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { Counter } from "../rivet/Counter"; - -export default function Home() { - return ; -} diff --git a/vendor/actors/examples/docs/actors-quickstart-next-js/rivet/Counter.tsx b/vendor/actors/examples/docs/actors-quickstart-next-js/rivet/Counter.tsx deleted file mode 100644 index f13b0c67..00000000 --- a/vendor/actors/examples/docs/actors-quickstart-next-js/rivet/Counter.tsx +++ /dev/null @@ -1,23 +0,0 @@ -"use client"; - -import { createRivetKit } from "@rivetkit/next-js/client"; -import { useState } from "react"; -import type { registry } from "./registry"; - -const { useActor } = createRivetKit({ - endpoint: process.env.NEXT_PUBLIC_RIVET_ENDPOINT ?? "http://localhost:6420", -}); - -export function Counter() { - const [count, setCount] = useState(0); - const counter = useActor({ name: "counter", key: ["my-counter"] }); - - counter.useEvent("newCount", (value: number) => setCount(value)); - - return ( -
-

Count: {count}

- -
- ); -} diff --git a/vendor/actors/examples/docs/actors-quickstart-next-js/rivet/node.ts b/vendor/actors/examples/docs/actors-quickstart-next-js/rivet/node.ts deleted file mode 100644 index aa0ee6ed..00000000 --- a/vendor/actors/examples/docs/actors-quickstart-next-js/rivet/node.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { registry } from "./registry"; - -registry.start(); diff --git a/vendor/actors/examples/docs/actors-quickstart-next-js/rivet/registry.ts b/vendor/actors/examples/docs/actors-quickstart-next-js/rivet/registry.ts deleted file mode 100644 index 4afe732a..00000000 --- a/vendor/actors/examples/docs/actors-quickstart-next-js/rivet/registry.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { actor, setup } from "rivetkit"; - -export const counter = actor({ - state: { count: 0 }, - actions: { - increment: (c, x: number) => { - c.state.count += x; - c.broadcast("newCount", c.state.count); - return c.state.count; - }, - }, -}); - -export const registry = setup({ - use: { counter }, -}); diff --git a/vendor/actors/examples/docs/actors-quickstart-react/index.ts b/vendor/actors/examples/docs/actors-quickstart-react/backend/index.ts similarity index 100% rename from vendor/actors/examples/docs/actors-quickstart-react/index.ts rename to vendor/actors/examples/docs/actors-quickstart-react/backend/index.ts diff --git a/vendor/actors/examples/docs/actors-quickstart-react/Counter.tsx b/vendor/actors/examples/docs/actors-quickstart-react/frontend/Counter.tsx similarity index 85% rename from vendor/actors/examples/docs/actors-quickstart-react/Counter.tsx rename to vendor/actors/examples/docs/actors-quickstart-react/frontend/Counter.tsx index a62ee024..26aa5be7 100644 --- a/vendor/actors/examples/docs/actors-quickstart-react/Counter.tsx +++ b/vendor/actors/examples/docs/actors-quickstart-react/frontend/Counter.tsx @@ -1,16 +1,16 @@ import { createRivetKit } from "@rivetkit/react"; import { useState } from "react"; -import type { registry } from "./index"; +import type { registry } from "../backend/index"; const { useActor } = createRivetKit("http://localhost:6420"); -function Counter() { +export function Counter() { const [count, setCount] = useState(0); // Get or create a counter actor for the key "my-counter" const counter = useActor({ name: "counter", - key: ["my-counter"] + key: ["my-counter"], }); // Listen to realtime events diff --git a/vendor/actors/examples/docs/actors-quickstart-react/frontend/main.tsx b/vendor/actors/examples/docs/actors-quickstart-react/frontend/main.tsx new file mode 100644 index 00000000..a8e4ea9d --- /dev/null +++ b/vendor/actors/examples/docs/actors-quickstart-react/frontend/main.tsx @@ -0,0 +1,9 @@ +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import { Counter } from "./Counter"; + +createRoot(document.getElementById("root")!).render( + + + , +); diff --git a/vendor/actors/examples/docs/actors-versions/programmatic-version.ts b/vendor/actors/examples/docs/actors-versions/programmatic-version.ts deleted file mode 100644 index 9763d971..00000000 --- a/vendor/actors/examples/docs/actors-versions/programmatic-version.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { actor, setup } from "rivetkit"; - -const myActor = actor({ state: {}, actions: {} }); - -const registry = setup({ - use: { myActor }, - envoy: { - version: 2, - }, -}); diff --git a/vendor/actors/examples/docs/api/inspector-action.ts b/vendor/actors/examples/docs/api/inspector-action.ts deleted file mode 100644 index 78a79d4a..00000000 --- a/vendor/actors/examples/docs/api/inspector-action.ts +++ /dev/null @@ -1,14 +0,0 @@ -const endpoint = "https://api.rivet.dev"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/action/increment`, - { - method: "POST", - headers: { - Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ args: [1] }), - }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/actors/examples/docs/api/inspector-connections.ts b/vendor/actors/examples/docs/api/inspector-connections.ts deleted file mode 100644 index e9bb0ade..00000000 --- a/vendor/actors/examples/docs/api/inspector-connections.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://api.rivet.dev"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/connections`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/actors/examples/docs/api/inspector-database-execute.ts b/vendor/actors/examples/docs/api/inspector-database-execute.ts deleted file mode 100644 index d657c202..00000000 --- a/vendor/actors/examples/docs/api/inspector-database-execute.ts +++ /dev/null @@ -1,17 +0,0 @@ -const endpoint = "https://api.rivet.dev"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/database/execute`, - { - method: "POST", - headers: { - Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ - sql: "SELECT * FROM users WHERE id = ?", - args: ["user-123"], - }), - }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/actors/examples/docs/api/inspector-database-rows.ts b/vendor/actors/examples/docs/api/inspector-database-rows.ts deleted file mode 100644 index 060781c7..00000000 --- a/vendor/actors/examples/docs/api/inspector-database-rows.ts +++ /dev/null @@ -1,12 +0,0 @@ -const endpoint = "https://api.rivet.dev"; -const query = new URLSearchParams({ - table: "users", - limit: "100", - offset: "0", -}); -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/database/rows?${query}`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/actors/examples/docs/api/inspector-database-schema.ts b/vendor/actors/examples/docs/api/inspector-database-schema.ts deleted file mode 100644 index b95bd360..00000000 --- a/vendor/actors/examples/docs/api/inspector-database-schema.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://api.rivet.dev"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/database/schema`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/actors/examples/docs/api/inspector-queue-delete.ts b/vendor/actors/examples/docs/api/inspector-queue-delete.ts deleted file mode 100644 index 0786860a..00000000 --- a/vendor/actors/examples/docs/api/inspector-queue-delete.ts +++ /dev/null @@ -1,10 +0,0 @@ -const endpoint = "https://api.rivet.dev"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/queue`, - { - method: "DELETE", - headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` }, - }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/actors/examples/docs/api/inspector-queue-get.ts b/vendor/actors/examples/docs/api/inspector-queue-get.ts deleted file mode 100644 index 82528552..00000000 --- a/vendor/actors/examples/docs/api/inspector-queue-get.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://api.rivet.dev"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/queue?limit=50`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/actors/examples/docs/api/inspector-queue-post.ts b/vendor/actors/examples/docs/api/inspector-queue-post.ts deleted file mode 100644 index 9a5d80ad..00000000 --- a/vendor/actors/examples/docs/api/inspector-queue-post.ts +++ /dev/null @@ -1,14 +0,0 @@ -const endpoint = "https://api.rivet.dev"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/queue`, - { - method: "POST", - headers: { - Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ name: "increment", body: { amount: 1 } }), - }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/actors/examples/docs/api/inspector-rpcs.ts b/vendor/actors/examples/docs/api/inspector-rpcs.ts deleted file mode 100644 index 4f9f0c7c..00000000 --- a/vendor/actors/examples/docs/api/inspector-rpcs.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://api.rivet.dev"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/rpcs`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/actors/examples/docs/api/inspector-state-get.ts b/vendor/actors/examples/docs/api/inspector-state-get.ts deleted file mode 100644 index 53eacb7e..00000000 --- a/vendor/actors/examples/docs/api/inspector-state-get.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://api.rivet.dev"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/state`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/actors/examples/docs/api/inspector-state-patch.ts b/vendor/actors/examples/docs/api/inspector-state-patch.ts deleted file mode 100644 index bcdf52c1..00000000 --- a/vendor/actors/examples/docs/api/inspector-state-patch.ts +++ /dev/null @@ -1,14 +0,0 @@ -const endpoint = "https://api.rivet.dev"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/state`, - { - method: "PATCH", - headers: { - Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ state: { count: 2 } }), - }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/actors/examples/docs/api/inspector-summary.ts b/vendor/actors/examples/docs/api/inspector-summary.ts deleted file mode 100644 index 5ddc54d9..00000000 --- a/vendor/actors/examples/docs/api/inspector-summary.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://api.rivet.dev"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/summary`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/actors/examples/docs/api/inspector-traces.ts b/vendor/actors/examples/docs/api/inspector-traces.ts deleted file mode 100644 index c9fc7ca1..00000000 --- a/vendor/actors/examples/docs/api/inspector-traces.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://api.rivet.dev"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/traces?startMs=0&limit=100`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/actors/examples/docs/api/inspector-workflow-history.ts b/vendor/actors/examples/docs/api/inspector-workflow-history.ts deleted file mode 100644 index 0e1ed297..00000000 --- a/vendor/actors/examples/docs/api/inspector-workflow-history.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://api.rivet.dev"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/workflow-history`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/actors/examples/docs/api/inspector-workflow-replay.ts b/vendor/actors/examples/docs/api/inspector-workflow-replay.ts deleted file mode 100644 index 23736edb..00000000 --- a/vendor/actors/examples/docs/api/inspector-workflow-replay.ts +++ /dev/null @@ -1,14 +0,0 @@ -const endpoint = "https://api.rivet.dev"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/workflow/replay`, - { - method: "POST", - headers: { - Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ entryId: "entry-123" }), - }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/actors/examples/docs/api/workers-configs-delete.ts b/vendor/actors/examples/docs/api/pools-delete.ts similarity index 51% rename from vendor/actors/examples/docs/api/workers-configs-delete.ts rename to vendor/actors/examples/docs/api/pools-delete.ts index f830246e..ad9c5134 100644 --- a/vendor/actors/examples/docs/api/workers-configs-delete.ts +++ b/vendor/actors/examples/docs/api/pools-delete.ts @@ -1,13 +1,16 @@ const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; -const workerName = process.env.RUNNER_NAME ?? "default"; +const pool = process.env.RIVET_POOL ?? "default"; const params = new URLSearchParams({ namespace }); const response = await fetch( - `${endpoint}/runner-configs/${encodeURIComponent(workerName)}?${params}`, - { method: "DELETE", headers: { Authorization: `Bearer ${token}` } }, + `${endpoint}/pools/${encodeURIComponent(pool)}?${params}`, + { + method: "DELETE", + headers: { Authorization: `Bearer ${token}` }, + }, ); -console.log(response.ok); +console.log(response.status); export {}; diff --git a/vendor/actors/examples/docs/api/pools-get.ts b/vendor/actors/examples/docs/api/pools-get.ts new file mode 100644 index 00000000..852a5f71 --- /dev/null +++ b/vendor/actors/examples/docs/api/pools-get.ts @@ -0,0 +1,13 @@ +const endpoint = "https://api.rivet.dev"; +const namespace = process.env.RIVET_NAMESPACE ?? "default"; +const token = process.env.RIVET_TOKEN ?? ""; +const pool = process.env.RIVET_POOL ?? "default"; + +const params = new URLSearchParams({ namespace }); +const response = await fetch( + `${endpoint}/pools/${encodeURIComponent(pool)}?${params}`, + { headers: { Authorization: `Bearer ${token}` } }, +); +console.log(await response.json()); + +export {}; diff --git a/vendor/actors/examples/docs/api/pools-list-nodes.ts b/vendor/actors/examples/docs/api/pools-list-nodes.ts new file mode 100644 index 00000000..b55c107f --- /dev/null +++ b/vendor/actors/examples/docs/api/pools-list-nodes.ts @@ -0,0 +1,14 @@ +const endpoint = "https://api.rivet.dev"; +const namespace = process.env.RIVET_NAMESPACE ?? "default"; +const token = process.env.RIVET_TOKEN ?? ""; +const pool = process.env.RIVET_POOL ?? "default"; + +const params = new URLSearchParams({ namespace }); +const response = await fetch( + `${endpoint}/pools/${encodeURIComponent(pool)}/nodes?${params}`, + { headers: { Authorization: `Bearer ${token}` } }, +); +const { nodes, pagination } = await response.json(); +console.log(nodes, pagination.cursor); + +export {}; diff --git a/vendor/actors/examples/docs/api/workers-configs-list.ts b/vendor/actors/examples/docs/api/pools-list.ts similarity index 63% rename from vendor/actors/examples/docs/api/workers-configs-list.ts rename to vendor/actors/examples/docs/api/pools-list.ts index 8f13f84f..eac08588 100644 --- a/vendor/actors/examples/docs/api/workers-configs-list.ts +++ b/vendor/actors/examples/docs/api/pools-list.ts @@ -3,10 +3,10 @@ const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; const params = new URLSearchParams({ namespace }); -const response = await fetch(`${endpoint}/runner-configs?${params}`, { +const response = await fetch(`${endpoint}/pools?${params}`, { headers: { Authorization: `Bearer ${token}` }, }); -const { runner_configs } = await response.json(); -console.log(runner_configs); +const { pools, pagination } = await response.json(); +console.log(pools, pagination.cursor); export {}; diff --git a/vendor/actors/examples/docs/api/workers-configs-upsert.ts b/vendor/actors/examples/docs/api/pools-upsert.ts similarity index 66% rename from vendor/actors/examples/docs/api/workers-configs-upsert.ts rename to vendor/actors/examples/docs/api/pools-upsert.ts index f46c7f76..0097c1c7 100644 --- a/vendor/actors/examples/docs/api/workers-configs-upsert.ts +++ b/vendor/actors/examples/docs/api/pools-upsert.ts @@ -1,18 +1,18 @@ const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; -const workerName = process.env.RUNNER_NAME ?? "default"; +const pool = process.env.RIVET_POOL ?? "default"; const params = new URLSearchParams({ namespace }); const response = await fetch( - `${endpoint}/runner-configs/${encodeURIComponent(workerName)}?${params}`, + `${endpoint}/pools/${encodeURIComponent(pool)}?${params}`, { method: "PUT", headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", }, - body: JSON.stringify({ datacenters: { local: { normal: {} } } }), + body: JSON.stringify({ drain_on_version_upgrade: true }), }, ); console.log(await response.json()); diff --git a/vendor/actors/examples/docs/api/workers-list.ts b/vendor/actors/examples/docs/api/workers-list.ts deleted file mode 100644 index 7d627ad4..00000000 --- a/vendor/actors/examples/docs/api/workers-list.ts +++ /dev/null @@ -1,12 +0,0 @@ -const endpoint = "https://api.rivet.dev"; -const namespace = process.env.RIVET_NAMESPACE ?? "default"; -const token = process.env.RIVET_TOKEN ?? ""; - -const params = new URLSearchParams({ namespace }); -const response = await fetch(`${endpoint}/envoys?${params}`, { - headers: { Authorization: `Bearer ${token}` }, -}); -const { envoys: workers, pagination } = await response.json(); -console.log(workers, pagination.cursor); - -export {}; diff --git a/vendor/actors/examples/docs/durable-streams/client.ts b/vendor/actors/examples/docs/durable-streams/client.ts new file mode 100644 index 00000000..97fdedf0 --- /dev/null +++ b/vendor/actors/examples/docs/durable-streams/client.ts @@ -0,0 +1,14 @@ +import { DurableStream } from "@durable-streams/client"; + +const stream = await DurableStream.create({ + url: "http://127.0.0.1:8642/durable-streams/v1/stream/demo", + contentType: "application/json", +}); + +await stream.append(JSON.stringify({ message: "hello" })); + +// Read from the beginning, then keep receiving new messages live +const res = await stream.stream<{ message: string }>(); +res.subscribeJson(async (batch) => { + for (const item of batch.items) console.log(item.message); +}); diff --git a/vendor/actors/examples/docs/durable-streams/create.ts b/vendor/actors/examples/docs/durable-streams/create.ts new file mode 100644 index 00000000..582ec8f2 --- /dev/null +++ b/vendor/actors/examples/docs/durable-streams/create.ts @@ -0,0 +1,11 @@ +import { DurableStream } from "@durable-streams/client"; + +// One stream per chat session +const stream = await DurableStream.create({ + url: "http://127.0.0.1:8642/durable-streams/v1/stream/chat/session-1", + contentType: "application/json", + // Delete the stream after a day with no reads or writes + ttlSeconds: 86400, +}); + +console.log("created", stream.url); diff --git a/vendor/actors/examples/docs/durable-streams/producer.ts b/vendor/actors/examples/docs/durable-streams/producer.ts new file mode 100644 index 00000000..eb2f8a16 --- /dev/null +++ b/vendor/actors/examples/docs/durable-streams/producer.ts @@ -0,0 +1,21 @@ +import { DurableStream, IdempotentProducer } from "@durable-streams/client"; + +const stream = new DurableStream({ + url: "http://127.0.0.1:8642/durable-streams/v1/stream/chat/session-1", + contentType: "application/json", +}); + +// Keep the producer ID the same across restarts. With autoClaim, a restarted +// agent takes over and the old one can no longer write. +const producer = new IdempotentProducer(stream, "agent-session-1", { + autoClaim: true, + onError: (error) => console.error("append failed", error), +}); + +for (const token of ["It's", " sunny", " today"]) { + producer.append(JSON.stringify({ token })); +} + +// Wait until every token is stored, then close the stream +await producer.flush(); +await producer.close(); diff --git a/vendor/actors/examples/docs/durable-streams/read-history.ts b/vendor/actors/examples/docs/durable-streams/read-history.ts new file mode 100644 index 00000000..457570d7 --- /dev/null +++ b/vendor/actors/examples/docs/durable-streams/read-history.ts @@ -0,0 +1,10 @@ +import { stream } from "@durable-streams/client"; + +const url = "http://127.0.0.1:8642/durable-streams/v1/stream/chat/session-1"; + +// Everything written so far, then stop +const res = await stream<{ token: string }>({ url, offset: "-1", live: false }); +const messages = await res.json(); + +console.log(messages); +console.log("read from here next:", res.offset); diff --git a/vendor/actors/examples/docs/durable-streams/read-live.ts b/vendor/actors/examples/docs/durable-streams/read-live.ts new file mode 100644 index 00000000..362854f3 --- /dev/null +++ b/vendor/actors/examples/docs/durable-streams/read-live.ts @@ -0,0 +1,14 @@ +import { stream } from "@durable-streams/client"; + +const url = "http://127.0.0.1:8642/durable-streams/v1/stream/chat/session-1"; + +// "-1" starts at the beginning. Pass a saved offset to pick up where you left off. +const savedOffset: string = "-1"; + +const res = await stream<{ token: string }>({ url, offset: savedOffset, live: "sse" }); +res.subscribeJson(async (batch) => { + for (const item of batch.items) console.log(item.token); + + // Save this to resume from the same place after a refresh + console.log("offset", batch.offset); +}); diff --git a/vendor/actors/examples/docs/durable-streams/write.ts b/vendor/actors/examples/docs/durable-streams/write.ts new file mode 100644 index 00000000..c68ab7ce --- /dev/null +++ b/vendor/actors/examples/docs/durable-streams/write.ts @@ -0,0 +1,13 @@ +import { DurableStream } from "@durable-streams/client"; + +const stream = new DurableStream({ + url: "http://127.0.0.1:8642/durable-streams/v1/stream/chat/session-1", + contentType: "application/json", +}); + +// Each append is one message +await stream.append(JSON.stringify({ token: "It's" })); +await stream.append(JSON.stringify({ token: " sunny" })); + +// Close with a final message: readers know the reply is complete +await stream.close({ body: JSON.stringify({ token: "." }) }); diff --git a/vendor/actors/examples/docs/general-edge/client.ts b/vendor/actors/examples/docs/general-edge/client.ts new file mode 100644 index 00000000..fde898f5 --- /dev/null +++ b/vendor/actors/examples/docs/general-edge/client.ts @@ -0,0 +1,12 @@ +import { createClient } from "rivetkit/client"; +import { actor, setup } from "rivetkit"; + +const example = actor({ state: {}, actions: {} }); +const registry = setup({ use: { example } }); + +const client = createClient("http://localhost:6420"); + +// Create actor in a specific region using getOrCreate +const actorHandle = client.example.getOrCreate(["my-actor"], { + createInRegion: "atl" +}); diff --git a/vendor/actors/examples/docs/package.json b/vendor/actors/examples/docs/package.json index a0e98db3..3ddcea78 100644 --- a/vendor/actors/examples/docs/package.json +++ b/vendor/actors/examples/docs/package.json @@ -1,4 +1,5 @@ { + "license": "MIT", "name": "docs-snippets", "version": "2.0.21", "private": true, @@ -11,10 +12,7 @@ "rivetkit": "workspace:*", "@rivetkit/react": "workspace:*", "@rivetkit/engine-api-full": "workspace:*", - "@rivetkit/next-js": "workspace:*", - "@rivetkit/cloudflare-workers": "workspace:*", "@rivetkit/rivetkit-wasm": "workspace:*", - "@rivetkit/supabase": "workspace:*", "@rivetkit/effect": "workspace:*", "effect": "4.0.0", "@effect/platform-node": "4.0.0", diff --git a/vendor/actors/examples/docs/tsconfig.json b/vendor/actors/examples/docs/tsconfig.json index 498e3a9a..ee88fd1d 100644 --- a/vendor/actors/examples/docs/tsconfig.json +++ b/vendor/actors/examples/docs/tsconfig.json @@ -13,5 +13,12 @@ "jsx": "react-jsx" }, "include": ["**/*.ts", "**/*.tsx"], - "exclude": ["node_modules"] + "exclude": [ + "node_modules", + "actors-quickstart-next-js", + "general-http-server/elysia-handler.ts", + "general-http-server/hono-handler.ts", + "general-http-server/serve.ts", + "actors-actions/calling-backend.ts" + ] } diff --git a/vendor/actors/examples/multiplayer-game-patterns/package.json b/vendor/actors/examples/multiplayer-game-patterns/package.json index 53a751e4..ba227fea 100644 --- a/vendor/actors/examples/multiplayer-game-patterns/package.json +++ b/vendor/actors/examples/multiplayer-game-patterns/package.json @@ -1,49 +1,49 @@ { - "name": "example-multiplayer-game-patterns", - "version": "2.0.21", - "private": true, - "type": "module", - "scripts": { - "dev": "concurrently -n server,vite \"tsx --watch src/index.ts\" \"vite\"", - "dev:server": "tsx --watch src/index.ts", - "check-types": "tsc --noEmit", - "test": "vitest run", - "build": "vite build", - "start": "tsx src/index.ts" - }, - "devDependencies": { - "@types/node": "^22.13.9", - "@types/react": "^18.2.0", - "@types/react-dom": "^18.2.0", - "@types/three": "^0.171.0", - "@vitejs/plugin-react": "^4.2.0", - "concurrently": "^9.0.0", - "tsx": "^3.12.7", - "typescript": "^5.5.2", - "vite": "^5.0.0", - "vitest": "^3.1.1" - }, - "dependencies": { - "@dimforge/rapier2d-compat": "^0.14.0", - "@dimforge/rapier3d-compat": "^0.14.0", - "lucide-react": "^0.439.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "rivetkit": "workspace:*", - "three": "^0.171.0" - }, - "stableVersion": "0.8.0", - "template": { - "technologies": [ - "react", - "typescript" - ], - "tags": [ - "real-time", - "game" - ], - "frontendPort": 5173, - "skipVercel": true - }, - "license": "MIT" + "name": "example-multiplayer-game-patterns", + "version": "2.0.21", + "private": true, + "type": "module", + "scripts": { + "dev": "concurrently -n server,vite \"tsx --watch src/index.ts\" \"vite\"", + "dev:server": "tsx --watch src/index.ts", + "check-types": "tsc --noEmit", + "test": "vitest run", + "build": "vite build", + "start": "tsx src/index.ts" + }, + "devDependencies": { + "@types/node": "^22.13.9", + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "@types/three": "^0.171.0", + "@vitejs/plugin-react": "^4.2.0", + "concurrently": "^9.0.0", + "tsx": "^3.12.7", + "typescript": "^5.5.2", + "vite": "^5.0.0", + "vitest": "^3.1.1" + }, + "dependencies": { + "@dimforge/rapier2d-compat": "^0.14.0", + "@dimforge/rapier3d-compat": "^0.14.0", + "lucide-react": "^0.439.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "rivetkit": "workspace:*", + "three": "^0.171.0" + }, + "stableVersion": "0.8.0", + "template": { + "technologies": [ + "react", + "typescript" + ], + "tags": [ + "real-time", + "game" + ], + "frontendPort": 5173, + "skipVercel": true + }, + "license": "MIT" } diff --git a/vendor/actors/examples/multiplayer-game-patterns/src/actors/idle/world.ts b/vendor/actors/examples/multiplayer-game-patterns/src/actors/idle/world.ts index 9ec53135..a7768b28 100644 --- a/vendor/actors/examples/multiplayer-game-patterns/src/actors/idle/world.ts +++ b/vendor/actors/examples/multiplayer-game-patterns/src/actors/idle/world.ts @@ -150,7 +150,7 @@ async function scheduleCollection( ): Promise { await c.cron.every({ name: `collect-production:${buildingId}`, - intervalMs, + interval: intervalMs, action: "collectProduction", args: [{ buildingId }], maxHistory: 0, diff --git a/vendor/actors/examples/multiplayer-game-patterns/tests/matchmaking-and-session-patterns.test.ts b/vendor/actors/examples/multiplayer-game-patterns/tests/matchmaking-and-session-patterns.test.ts deleted file mode 100644 index 311d1861..00000000 --- a/vendor/actors/examples/multiplayer-game-patterns/tests/matchmaking-and-session-patterns.test.ts +++ /dev/null @@ -1,717 +0,0 @@ -import { setupTest } from "rivetkit/test"; -import { describe, expect, test } from "vitest"; -import { registry } from "../src/actors/index.ts"; -import { CHUNK_SIZE, WORLD_ID } from "../src/actors/open-world/config.ts"; - -const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); - -type QueueResult = { - status: "completed" | "timedOut"; - response?: T; -}; - -type RawQueueConnection = { - send( - name: string, - body: unknown, - options: { wait: true; timeout?: number }, - ): Promise>; -}; - -describe("matchmaking and session patterns", () => { - test("io-style open lobby + 10 tps match with movement", async (ctx) => { - const { client } = await setupTest(ctx, registry); - - const mm = client.ioStyleMatchmaker.getOrCreate(["main"]).connect(); - const firstQueueResult = await mm.send( - "findLobby", - {}, - { wait: true, timeout: 1_000 }, - ); - const secondQueueResult = await mm.send( - "findLobby", - {}, - { wait: true, timeout: 1_000 }, - ); - expect(firstQueueResult?.status).toBe("completed"); - expect(secondQueueResult?.status).toBe("completed"); - const firstResponse = ( - firstQueueResult as { - response?: { matchId?: string; playerId?: string }; - } - )?.response; - const secondResponse = ( - secondQueueResult as { - response?: { matchId?: string; playerId?: string }; - } - )?.response; - expect(firstResponse?.playerId).toBeTypeOf("string"); - expect(secondResponse?.playerId).toBeTypeOf("string"); - expect(secondResponse?.matchId).toBe(firstResponse?.matchId); - - const a = client.ioStyleMatch - .getOrCreate([firstResponse?.matchId!], { - params: { - playerId: firstResponse?.playerId!, - }, - }) - .connect(); - const b = client.ioStyleMatch - .getOrCreate([firstResponse?.matchId!], { - params: { - playerId: secondResponse?.playerId!, - }, - }) - .connect(); - await sleep(260); - - const snapshot = await a.getSnapshot(); - expect(snapshot.playerCount).toBe(2); - expect(snapshot.tick).toBeGreaterThanOrEqual(2); - expect(Object.keys(snapshot.players)).toHaveLength(2); - expect(snapshot.worldSize).toBe(600); - - const initialX = snapshot.players[firstResponse?.playerId!]?.x; - await a.setInput({ inputX: 1, inputY: 0 }); - await sleep(350); - - const moved = await a.getSnapshot(); - expect(moved.players[firstResponse?.playerId!]?.x).toBeGreaterThan( - initialX, - ); - - await Promise.all([a.dispose(), b.dispose(), mm.dispose()]); - }, 15_000); - - test("arena queue-fill matchmaking with hybrid movement and hitscan combat", async (ctx) => { - const { client } = await setupTest(ctx, registry); - - interface Assignment { - matchId: string; - playerId: string; - teamId: number; - mode: string; - } - - const mm = client.arenaMatchmaker.getOrCreate(["main"]).connect(); - const results = await Promise.all( - Array.from({ length: 4 }, () => mm.queueForMatch({ mode: "duo" })), - ); - - const queueEntries = results.map((r) => { - const response = r as { playerId?: string }; - expect(response.playerId).toBeTypeOf("string"); - return { - playerId: response.playerId!, - }; - }); - - const assignments: Assignment[] = []; - for (const entry of queueEntries) { - let assignment: Assignment | null = null; - for (let i = 0; i < 50 && !assignment; i++) { - assignment = (await mm.getAssignment( - entry, - )) as Assignment | null; - if (!assignment) await sleep(100); - } - expect(assignment).not.toBeNull(); - expect(assignment?.matchId).toBeTypeOf("string"); - assignments.push(assignment!); - } - - const matchId = assignments[0]?.matchId; - expect(assignments.every((a) => a.matchId === matchId)).toBe(true); - - const conns = assignments.map((a) => - client.arenaMatch - .get([a.matchId], { params: { playerId: a.playerId } }) - .connect(), - ); - await sleep(200); - - const player0Id = assignments[0]?.playerId; - const snap1 = await conns[0]?.getSnapshot(); - expect(snap1.phase).toBe("live"); - expect(Object.keys(snap1.players)).toHaveLength(4); - expect(snap1.worldSize).toBe(600); - - const initialX = snap1.players[player0Id]?.x; - const initialY = snap1.players[player0Id]?.y; - await conns[0]?.updatePosition({ x: initialX + 10, y: initialY }); - await sleep(100); - const snap2 = await conns[0]?.getSnapshot(); - expect(snap2.players[player0Id]?.x).toBeCloseTo(initialX + 10, 0); - - const targetPlayerId = assignments[1]?.playerId; - for (let step = 0; step < 30; step++) { - const snapStep = await conns[0]?.getSnapshot(); - const me = snapStep.players[player0Id]!; - const target = snapStep.players[targetPlayerId]!; - const dx = target.x - me.x; - const dy = target.y - me.y; - const dist = Math.sqrt(dx * dx + dy * dy); - if (dist < 50) break; - const moveBy = Math.min(dist - 30, 40); - await conns[0]?.updatePosition({ - x: me.x + (dx / dist) * moveBy, - y: me.y + (dy / dist) * moveBy, - }); - await sleep(60); - } - - let scored = false; - for (let attempt = 0; attempt < 6 && !scored; attempt++) { - const snapBeforeShoot = await conns[0]?.getSnapshot(); - const mePos = snapBeforeShoot.players[player0Id]!; - const targetPos = snapBeforeShoot.players[targetPlayerId]!; - const dx = targetPos.x - mePos.x; - const dy = targetPos.y - mePos.y; - const mag = Math.sqrt(dx * dx + dy * dy); - if (mag === 0) continue; - await conns[0]?.shoot({ dirX: dx / mag, dirY: dy / mag }); - await sleep(100); - const afterShoot = await conns[0]?.getSnapshot(); - scored = afterShoot.players[player0Id]?.score >= 1; - } - const snap3 = await conns[0]?.getSnapshot(); - expect(snap3.phase).toBe("live"); - expect(snap3.players[player0Id]).toBeDefined(); - - await Promise.all([...conns.map((c) => c.dispose()), mm.dispose()]); - }, 15_000); - - test("party lobby with host controls and member management", async (ctx) => { - const { client } = await setupTest(ctx, registry); - - const mm = client.partyMatchmaker.getOrCreate(["main"]).connect(); - const createResult = await mm.send( - "createParty", - { hostName: "Host" }, - { wait: true, timeout: 5_000 }, - ); - const createResponse = ( - createResult as { - response?: { - matchId: string; - playerId: string; - partyCode: string; - joinToken: string; - playerName: string; - }; - } - )?.response; - expect(createResponse?.matchId).toBeTypeOf("string"); - expect(createResponse?.partyCode).toHaveLength(6); - if (!createResponse) - throw new Error("expected party creation response"); - - const hostConn = client.partyMatch - .get([createResponse.matchId], { - params: { - playerId: createResponse.playerId, - joinToken: createResponse.joinToken, - }, - }) - .connect(); - await sleep(200); - - const snap1 = await hostConn.getSnapshot(); - expect(snap1.partyCode).toBe(createResponse?.partyCode); - expect(snap1.phase).toBe("waiting"); - expect(Object.keys(snap1.members)).toHaveLength(1); - const hostMember = snap1.members[createResponse.playerId]; - expect(hostMember.isHost).toBe(true); - - const joinResult = await (mm as RawQueueConnection).send<{ - matchId: string; - playerId: string; - joinToken: string; - playerName: string; - }>( - "joinParty", - { partyCode: createResponse.partyCode, playerName: "Player2" }, - { wait: true, timeout: 5_000 }, - ); - const joinResponse = joinResult.response; - expect(joinResponse?.matchId).toBe(createResponse?.matchId); - if (!joinResponse) throw new Error("expected party join response"); - - const p2Conn = client.partyMatch - .get([joinResponse.matchId], { - params: { - playerId: joinResponse.playerId, - joinToken: joinResponse.joinToken, - }, - }) - .connect(); - await sleep(200); - - const snap2 = await hostConn.getSnapshot(); - expect(Object.keys(snap2.members)).toHaveLength(2); - - await p2Conn.toggleReady(); - await sleep(100); - await hostConn.startGame(); - await sleep(100); - - const snap3 = await hostConn.getSnapshot(); - expect(snap3.phase).toBe("playing"); - - await hostConn.finishGame(); - await sleep(100); - - const snap4 = await hostConn.getSnapshot(); - expect(snap4.phase).toBe("finished"); - - await p2Conn.dispose(); - await sleep(100); - - const snap5 = await hostConn.getSnapshot(); - expect(Object.keys(snap5.members)).toHaveLength(1); - - await Promise.all([hostConn.dispose(), mm.dispose()]); - }, 15_000); - - test("turn-based tic-tac-toe with moves and win detection", async (ctx) => { - const { client } = await setupTest(ctx, registry); - - const mm = client.turnBasedMatchmaker.getOrCreate(["main"]).connect(); - - const createResult = await mm.send( - "createGame", - { playerName: "PlayerX" }, - { wait: true, timeout: 5_000 }, - ); - const createResponse = ( - createResult as { - response?: { - matchId: string; - playerId: string; - inviteCode: string; - }; - } - )?.response; - expect(createResponse?.matchId).toBeTypeOf("string"); - expect(createResponse?.inviteCode).toHaveLength(6); - if (!createResponse) throw new Error("expected game creation response"); - - const joinResult = await (mm as RawQueueConnection).send<{ - matchId: string; - playerId: string; - }>( - "joinByCode", - { inviteCode: createResponse.inviteCode, playerName: "PlayerO" }, - { wait: true, timeout: 5_000 }, - ); - const joinResponse = joinResult.response; - expect(joinResponse?.matchId).toBe(createResponse?.matchId); - if (!joinResponse) throw new Error("expected game join response"); - - const xConn = client.turnBasedMatch - .get([createResponse.matchId], { - params: { playerId: createResponse.playerId }, - }) - .connect(); - const oConn = client.turnBasedMatch - .get([joinResponse.matchId], { - params: { playerId: joinResponse.playerId }, - }) - .connect(); - await sleep(200); - - const snap1 = await xConn.getSnapshot(); - expect(snap1.currentTurn).toBe("X"); - expect(Object.keys(snap1.players)).toHaveLength(2); - - await xConn.makeMove({ row: 0, col: 0 }); - await sleep(50); - await oConn.makeMove({ row: 1, col: 0 }); - await sleep(50); - await xConn.makeMove({ row: 0, col: 1 }); - await sleep(50); - await oConn.makeMove({ row: 1, col: 1 }); - await sleep(50); - await xConn.makeMove({ row: 0, col: 2 }); - await sleep(100); - - const snap2 = await xConn.getSnapshot(); - expect(snap2.result).toBe("x_wins"); - expect(snap2.board[0]).toEqual(["X", "X", "X"]); - - await Promise.all([xConn.dispose(), oConn.dispose(), mm.dispose()]); - }, 15_000); - - test("turn-based public queue omits invite code and starts match", async (ctx) => { - const { client } = await setupTest(ctx, registry); - - const mm = client.turnBasedMatchmaker.getOrCreate(["main"]).connect(); - const q1 = (await mm.queueForMatch({ playerName: "PublicA" })) as { - playerId?: string; - }; - const q2 = (await mm.queueForMatch({ playerName: "PublicB" })) as { - playerId?: string; - }; - expect(q1.playerId).toBeTypeOf("string"); - expect(q2.playerId).toBeTypeOf("string"); - - type PublicAssignment = { - matchId: string; - playerId: string; - inviteCode?: string; - }; - - const waitAssignment = async ( - playerId: string, - ): Promise => { - for (let i = 0; i < 50; i++) { - const assignment = (await mm.getAssignment({ - playerId, - })) as PublicAssignment | null; - if (assignment) return assignment; - await sleep(100); - } - throw new Error("timed out waiting for public assignment"); - }; - - const a1 = await waitAssignment(q1.playerId!); - const a2 = await waitAssignment(q2.playerId!); - expect(a1.matchId).toBe(a2.matchId); - expect(a1.inviteCode).toBeUndefined(); - expect(a2.inviteCode).toBeUndefined(); - - const c1 = client.turnBasedMatch - .get([a1.matchId], { params: { playerId: a1.playerId } }) - .connect(); - const c2 = client.turnBasedMatch - .get([a2.matchId], { params: { playerId: a2.playerId } }) - .connect(); - await sleep(250); - - const snap = await c1.getSnapshot(); - expect(Object.keys(snap.players)).toHaveLength(2); - expect(snap.result).toBeNull(); - - await Promise.all([c1.dispose(), c2.dispose(), mm.dispose()]); - }, 15_000); - - test("ranked 1v1 matchmaking with ELO pairing", async (ctx) => { - const { client } = await setupTest(ctx, registry); - - interface RankedAssignment { - matchId: string; - username: string; - rating: number; - } - - const usernames = ["TestPlayer1", "TestPlayer2"]; - - const mm = client.rankedMatchmaker.getOrCreate(["main"]).connect(); - await Promise.all( - usernames.map((username) => mm.queueForMatch({ username })), - ); - - const assignments: RankedAssignment[] = []; - for (const username of usernames) { - let assignment: RankedAssignment | null = null; - for (let i = 0; i < 50 && !assignment; i++) { - assignment = (await mm.getAssignment({ - username, - })) as RankedAssignment | null; - if (!assignment) await sleep(100); - } - expect(assignment).not.toBeNull(); - expect(assignment?.matchId).toBeTypeOf("string"); - expect(assignment?.username).toBeTypeOf("string"); - assignments.push(assignment!); - } - - const conns = assignments.map((a) => - client.rankedMatch - .get([a.matchId], { params: { username: a.username } }) - .connect(), - ); - await sleep(200); - - const snap = await conns[0]?.getSnapshot(); - expect(snap.phase).toBe("live"); - expect(Object.keys(snap.players)).toHaveLength(2); - expect(snap.scoreLimit).toBe(5); - - await Promise.all([...conns.map((c) => c.dispose()), mm.dispose()]); - }, 15_000); - - test("ranked allows re-queueing the same usernames", async (ctx) => { - const { client } = await setupTest(ctx, registry); - - interface RankedAssignment { - matchId: string; - username: string; - rating: number; - } - - const usernames = ["RequeueA", "RequeueB"]; - const mm = client.rankedMatchmaker.getOrCreate(["main"]).connect(); - let previousMatchId: string | null = null; - - for (let round = 0; round < 2; round++) { - await Promise.all( - usernames.map((username) => mm.queueForMatch({ username })), - ); - - const assignments: RankedAssignment[] = []; - for (const username of usernames) { - let assignment: RankedAssignment | null = null; - for (let i = 0; i < 80 && !assignment; i++) { - const next = (await mm.getAssignment({ - username, - })) as RankedAssignment | null; - if ( - next && - (!previousMatchId || next.matchId !== previousMatchId) - ) { - assignment = next; - break; - } - await sleep(100); - } - expect(assignment).not.toBeNull(); - assignments.push(assignment!); - } - - const matchId = assignments[0]?.matchId; - expect(assignments.every((a) => a.matchId === matchId)).toBe(true); - previousMatchId = matchId; - - const conns = assignments.map((a) => - client.rankedMatch - .get([a.matchId], { params: { username: a.username } }) - .connect(), - ); - await sleep(200); - - const snap = await conns[0]?.getSnapshot(); - expect(Object.keys(snap.players)).toHaveLength(2); - - await Promise.all(conns.map((c) => c.dispose())); - await sleep(100); - } - - await mm.dispose(); - }, 20_000); - - test("battle-royale lobby matchmaking and snapshot", async (ctx) => { - const { client } = await setupTest(ctx, registry); - - const mm = client.battleRoyaleMatchmaker - .getOrCreate(["main"]) - .connect(); - const result1 = await mm.send( - "findMatch", - {}, - { wait: true, timeout: 5_000 }, - ); - const result2 = await mm.send( - "findMatch", - {}, - { wait: true, timeout: 5_000 }, - ); - const r1 = ( - result1 as { - response?: { - matchId: string; - playerId: string; - }; - } - )?.response; - const r2 = ( - result2 as { - response?: { - matchId: string; - playerId: string; - }; - } - )?.response; - expect(r1?.matchId).toBeTypeOf("string"); - expect(r2?.matchId).toBe(r1?.matchId); - if (!r1 || !r2) { - throw new Error("expected battle royale queue responses"); - } - - const a = client.battleRoyaleMatch - .get([r1.matchId], { - params: { - playerId: r1.playerId, - }, - }) - .connect(); - const b = client.battleRoyaleMatch - .get([r2.matchId], { - params: { - playerId: r2.playerId, - }, - }) - .connect(); - await sleep(300); - - const snap = await a.getSnapshot(); - expect(snap.phase).toBe("lobby"); - expect(snap.playerCount).toBe(2); - expect(snap.worldSize).toBe(1200); - expect(snap.capacity).toBe(16); - expect(Object.keys(snap.players)).toHaveLength(2); - - await Promise.all([a.dispose(), b.dispose(), mm.dispose()]); - }, 15_000); - - test("open-world chunk routing and movement", async (ctx) => { - const { client } = await setupTest(ctx, registry); - - const response = resolveChunkForPosition(600, 600); - expect(response.chunkKey).toEqual([WORLD_ID, 0, 0]); - expect(response?.spawnX).toBeTypeOf("number"); - expect(response?.spawnY).toBeTypeOf("number"); - - const chunk = client.openWorldChunk - .getOrCreate([WORLD_ID, "0", "0"]) - .connect(); - await chunk.addPlayer({ - name: "Explorer", - spawnX: response.spawnX, - spawnY: response.spawnY, - }); - await sleep(300); - - const snap = await chunk.getSnapshot(); - expect(snap.chunkX).toBe(0); - expect(snap.chunkY).toBe(0); - expect(snap.chunkSize).toBe(1200); - expect(Object.keys(snap.players)).toHaveLength(1); - const myConnId = ( - Object.entries(snap.players) as Array<[string, { name: string }]> - ).find(([, p]) => p.name === "Explorer")?.[0]; - expect(myConnId).toBeTypeOf("string"); - - await chunk.setInput({ inputX: 1, inputY: 0 }); - await sleep(350); - - const snap2 = await chunk.getSnapshot(); - const myPos = myConnId ? snap2.players[myConnId] : undefined; - expect(myPos).toBeDefined(); - expect(myPos?.x).toBeGreaterThan(600); - - await chunk.removePlayer(); - await chunk.dispose(); - }, 15_000); - - test("open-world chunk transfer moves player to new chunk", async (ctx) => { - const { client } = await setupTest(ctx, registry); - - const r1 = resolveChunkForPosition(1190, 600); - expect(r1.chunkKey).toEqual([WORLD_ID, 0, 0]); - - const chunk0 = client.openWorldChunk - .getOrCreate([WORLD_ID, "0", "0"]) - .connect(); - const chunk1 = client.openWorldChunk - .getOrCreate([WORLD_ID, "1", "0"]) - .connect(); - await chunk0.addPlayer({ - name: "Traveler", - spawnX: r1.spawnX, - spawnY: r1.spawnY, - }); - await sleep(200); - - await chunk0.setInput({ inputX: 1, inputY: 0 }); - await sleep(500); - - const snapAtEdge = await chunk0.getSnapshot(); - const travelerConnId = ( - Object.entries(snapAtEdge.players) as Array< - [string, { name: string }] - > - ).find(([, p]) => p.name === "Traveler")?.[0]; - const posAtEdge = travelerConnId - ? snapAtEdge.players[travelerConnId] - : undefined; - expect(posAtEdge).toBeDefined(); - expect(posAtEdge?.x).toBe(1199); - - if (!posAtEdge) throw new Error("expected traveler position"); - const absX = 0 * 1200 + posAtEdge.x + 1; - const absY = 0 * 1200 + posAtEdge.y; - const r2 = resolveChunkForPosition(absX, absY); - expect(r2.chunkKey).toEqual([WORLD_ID, 1, 0]); - expect(r2.spawnX).toBeTypeOf("number"); - expect(r2.spawnY).toBeTypeOf("number"); - - await chunk0.removePlayer(); - await chunk1.addPlayer({ - name: "Traveler", - spawnX: r2.spawnX, - spawnY: r2.spawnY, - }); - await sleep(300); - - const snapNewChunk = await chunk1.getSnapshot(); - expect(snapNewChunk.chunkX).toBe(1); - expect(snapNewChunk.chunkY).toBe(0); - const newTravelerConnId = ( - Object.entries(snapNewChunk.players) as Array< - [string, { name: string }] - > - ).find(([, p]) => p.name === "Traveler")?.[0]; - const newPos = newTravelerConnId - ? snapNewChunk.players[newTravelerConnId] - : undefined; - expect(newPos).toBeDefined(); - if (!newPos) throw new Error("traveler position missing"); - expect(newPos.x).toBeLessThan(100); - - await chunk1.setInput({ inputX: 1, inputY: 0 }); - await sleep(350); - const snapMoved = await chunk1.getSnapshot(); - const movedPos = newTravelerConnId - ? snapMoved.players[newTravelerConnId] - : undefined; - expect(movedPos).toBeDefined(); - expect(movedPos?.x).toBeGreaterThan(newPos?.x); - - await Promise.all([chunk0.dispose(), chunk1.dispose()]); - }, 15_000); - - test("idle building and production with leaderboard", async (ctx) => { - const { client } = await setupTest(ctx, registry); - - const playerId = crypto.randomUUID(); - const world = client.idleWorld.getOrCreate([playerId]).connect(); - - await world.initialize({ playerName: "Builder" }); - const state1 = await world.getState(); - expect(state1.playerName).toBe("Builder"); - expect(state1.resources).toBe(10); - expect(state1.buildings).toHaveLength(1); - expect(state1.buildings[0]?.typeId).toBe("farm"); - - const lb = client.idleLeaderboard.getOrCreate(["main"]).connect(); - await sleep(100); - const scores = await lb.getTopScores({ limit: 10 }); - expect(Array.isArray(scores)).toBe(true); - - await Promise.all([world.dispose(), lb.dispose()]); - }, 15_000); -}); - -function resolveChunkForPosition( - x: number, - y: number, -): { chunkKey: [string, number, number]; spawnX: number; spawnY: number } { - const chunkX = Math.floor(x / CHUNK_SIZE); - const chunkY = Math.floor(y / CHUNK_SIZE); - return { - chunkKey: [WORLD_ID, chunkX, chunkY], - spawnX: ((x % CHUNK_SIZE) + CHUNK_SIZE) % CHUNK_SIZE, - spawnY: ((y % CHUNK_SIZE) + CHUNK_SIZE) % CHUNK_SIZE, - }; -} diff --git a/vendor/actors/examples/multiplayer-game-patterns/vitest.config.ts b/vendor/actors/examples/multiplayer-game-patterns/vitest.config.ts deleted file mode 100644 index f913a97a..00000000 --- a/vendor/actors/examples/multiplayer-game-patterns/vitest.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { defineConfig } from "vitest/config"; - -export default defineConfig({ - server: { - port: 5173, - }, - test: { - include: ["tests/**/*.test.ts"], - }, -}); diff --git a/vendor/actors/examples/per-tenant-database/package.json b/vendor/actors/examples/per-tenant-database/package.json index 2a7b89f4..fc6dd707 100644 --- a/vendor/actors/examples/per-tenant-database/package.json +++ b/vendor/actors/examples/per-tenant-database/package.json @@ -23,10 +23,10 @@ "vitest": "^3.1.1" }, "dependencies": { - "@rivetkit/react": "^2.3.31", + "@rivetkit/react": "^3.0.1", "react": "^18.2.0", "react-dom": "^18.2.0", - "rivetkit": "^2.3.31" + "rivetkit": "^3.0.1" }, "stableVersion": "0.8.0", "license": "MIT" diff --git a/vendor/actors/examples/per-tenant-database/tests/per-tenant-database.test.ts b/vendor/actors/examples/per-tenant-database/tests/per-tenant-database.test.ts deleted file mode 100644 index e5138237..00000000 --- a/vendor/actors/examples/per-tenant-database/tests/per-tenant-database.test.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { setupTest } from "rivetkit/test"; -import { expect, test } from "vitest"; -import { registry } from "../src/index.ts"; - -test("Each company key gets its own SQLite database", async (ctx) => { - const { client } = await setupTest(ctx, registry); - const alpha = client.companyDatabase.getOrCreate(["Alpha Co"]); - const beta = client.companyDatabase.getOrCreate(["Beta Co"]); - - await alpha.addEmployee("Ava", "Engineering"); - await alpha.addProject("Phoenix", "active"); - await beta.addEmployee("Ben", "Sales"); - - const alphaEmployees = await alpha.listEmployees(); - const betaEmployees = await beta.listEmployees(); - const alphaProjects = await alpha.listProjects(); - const betaProjects = await beta.listProjects(); - - expect(alphaEmployees).toHaveLength(1); - expect(betaEmployees).toHaveLength(1); - expect(alphaEmployees[0].name).toBe("Ava"); - expect(betaEmployees[0].name).toBe("Ben"); - expect(alphaProjects).toHaveLength(1); - expect(betaProjects).toHaveLength(0); - - // Each tenant has its own tables, so both AUTOINCREMENT sequences start at 1. - expect(alphaEmployees[0].id).toBe(1); - expect(betaEmployees[0].id).toBe(1); - - const betaStats = await beta.getStats(); - expect(betaStats.employee_count).toBe(1); - expect(betaStats.project_count).toBe(0); -}); - -test("Stats reflect per-company rows", async (ctx) => { - const { client } = await setupTest(ctx, registry); - const company = client.companyDatabase.getOrCreate(["Stats Co"]); - - const initialStats = await company.getStats(); - expect(initialStats.employee_count).toBe(0); - expect(initialStats.project_count).toBe(0); - - await company.addEmployee("Lina", "Finance"); - await company.addEmployee("Omar", "Support"); - await company.addProject("Drift", "planning"); - - const updatedStats = await company.getStats(); - expect(updatedStats.employee_count).toBe(2); - expect(updatedStats.project_count).toBe(1); - expect(updatedStats.updated_at).toBeGreaterThanOrEqual( - updatedStats.created_at, - ); -}); diff --git a/vendor/actors/examples/per-tenant-database/vitest.config.ts b/vendor/actors/examples/per-tenant-database/vitest.config.ts deleted file mode 100644 index f913a97a..00000000 --- a/vendor/actors/examples/per-tenant-database/vitest.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { defineConfig } from "vitest/config"; - -export default defineConfig({ - server: { - port: 5173, - }, - test: { - include: ["tests/**/*.test.ts"], - }, -}); diff --git a/vendor/actors/examples/scheduling/tests/scheduling.test.ts b/vendor/actors/examples/scheduling/tests/scheduling.test.ts deleted file mode 100644 index 4a4d8c61..00000000 --- a/vendor/actors/examples/scheduling/tests/scheduling.test.ts +++ /dev/null @@ -1,224 +0,0 @@ -import { setupTest } from "rivetkit/test"; -import { describe, expect, test } from "vitest"; -import { registry, type Reminder } from "../src/index.ts"; - -// Helper to wait for a delay -const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); - -describe("reminder scheduling", () => { - test("triggers reminder after delay", async (ctx) => { - const { client } = await setupTest(ctx, registry); - const reminderClient = - client.reminderActor.getOrCreate("test-after-delay"); - const reminder = await reminderClient.scheduleReminder( - "Test reminder", - 100, - ); - - // Verify reminder was created - expect(reminder.id).toBeDefined(); - expect(reminder.message).toBe("Test reminder"); - expect(reminder.completedAt).toBeUndefined(); - - // Wait for the scheduled action to execute - await wait(150); - - const reminders = await reminderClient.getReminders(); - const completed = reminders.find((r: Reminder) => r.id === reminder.id); - - expect(completed?.completedAt).toBeDefined(); - }); - - test("schedules reminder at specific timestamp", async (ctx) => { - const { client } = await setupTest(ctx, registry); - const reminderClient = - client.reminderActor.getOrCreate("test-at-timestamp"); - const futureTime = Date.now() + 100; - const reminder = await reminderClient.scheduleReminderAt( - "Future reminder", - futureTime, - ); - - // Verify reminder was created - expect(reminder.scheduledAt).toBe(futureTime); - expect(reminder.completedAt).toBeUndefined(); - - // Wait for the scheduled time - await wait(150); - - const reminders = await reminderClient.getReminders(); - const completed = reminders.find((r: Reminder) => r.id === reminder.id); - - expect(completed?.completedAt).toBeDefined(); - }); - - test("passes correct arguments to scheduled actions", async (ctx) => { - const { client } = await setupTest(ctx, registry); - const reminderClient = - client.reminderActor.getOrCreate("test-arguments"); - - // Schedule multiple reminders with different IDs - const reminder1 = await reminderClient.scheduleReminder( - "First reminder", - 50, - ); - const reminder2 = await reminderClient.scheduleReminder( - "Second reminder", - 100, - ); - const reminder3 = await reminderClient.scheduleReminder( - "Third reminder", - 150, - ); - - // Wait for all to trigger - await wait(200); - - const reminders = await reminderClient.getReminders(); - - // Verify each reminder received the correct ID and was triggered - const completed1 = reminders.find( - (r: Reminder) => r.id === reminder1.id, - ); - const completed2 = reminders.find( - (r: Reminder) => r.id === reminder2.id, - ); - const completed3 = reminders.find( - (r: Reminder) => r.id === reminder3.id, - ); - - expect(completed1?.completedAt).toBeDefined(); - expect(completed2?.completedAt).toBeDefined(); - expect(completed3?.completedAt).toBeDefined(); - }); - - test("cancels scheduled reminder", async (ctx) => { - const { client } = await setupTest(ctx, registry); - const reminderClient = client.reminderActor.getOrCreate("test-cancel"); - const reminder = await reminderClient.scheduleReminder( - "To be cancelled", - 100, - ); - - // Cancel the reminder before it triggers - await reminderClient.cancelReminder(reminder.id); - - // Wait past the original trigger time - await wait(150); - - const reminders = await reminderClient.getReminders(); - const found = reminders.find((r: Reminder) => r.id === reminder.id); - - // Reminder should not exist (was removed from state) - expect(found).toBeUndefined(); - }); - - test("triggers multiple reminders in correct order", async (ctx) => { - const { client } = await setupTest(ctx, registry); - const reminderClient = - client.reminderActor.getOrCreate("test-multiple"); - - // Schedule 5 reminders with different delays - const reminder1 = await reminderClient.scheduleReminder( - "Reminder 1", - 50, - ); - const reminder2 = await reminderClient.scheduleReminder( - "Reminder 2", - 100, - ); - const reminder3 = await reminderClient.scheduleReminder( - "Reminder 3", - 150, - ); - const reminder4 = await reminderClient.scheduleReminder( - "Reminder 4", - 200, - ); - const reminder5 = await reminderClient.scheduleReminder( - "Reminder 5", - 250, - ); - - // Wait for all to complete - await wait(300); - - const reminders = await reminderClient.getReminders(); - - // Verify all are completed - expect( - reminders.find((r: Reminder) => r.id === reminder1.id)?.completedAt, - ).toBeDefined(); - expect( - reminders.find((r: Reminder) => r.id === reminder2.id)?.completedAt, - ).toBeDefined(); - expect( - reminders.find((r: Reminder) => r.id === reminder3.id)?.completedAt, - ).toBeDefined(); - expect( - reminders.find((r: Reminder) => r.id === reminder4.id)?.completedAt, - ).toBeDefined(); - expect( - reminders.find((r: Reminder) => r.id === reminder5.id)?.completedAt, - ).toBeDefined(); - - const stats = await reminderClient.getStats(); - expect(stats.completed).toBe(5); - }); - - // Skipping restart test as direct actor access is not available in setupTest - test.skip("scheduled actions persist across actor restarts", async (ctx) => { - const { client } = await setupTest(ctx, registry); - const reminderClient = client.reminderActor.getOrCreate("test-restart"); - const reminder = await reminderClient.scheduleReminder( - "Persistent reminder", - 100, - ); - - // This test would require direct access to the actor instance to stop it - // which is not provided by setupTest - - await wait(150); - - const reminders = await reminderClient.getReminders(); - const completed = reminders.find((r: Reminder) => r.id === reminder.id); - - expect(completed?.completedAt).toBeDefined(); - }); - - test("updates stats correctly", async (ctx) => { - const { client } = await setupTest(ctx, registry); - const reminderClient = client.reminderActor.getOrCreate("test-stats"); - - let stats = await reminderClient.getStats(); - expect(stats.total).toBe(0); - expect(stats.completed).toBe(0); - expect(stats.pending).toBe(0); - - // Schedule some reminders - await reminderClient.scheduleReminder("Reminder 1", 50); - await reminderClient.scheduleReminder("Reminder 2", 100); - await reminderClient.scheduleReminder("Reminder 3", 150); - - stats = await reminderClient.getStats(); - expect(stats.total).toBe(3); - expect(stats.pending).toBe(3); - expect(stats.completed).toBe(0); - - // Wait for first reminder to trigger - await wait(70); - - stats = await reminderClient.getStats(); - expect(stats.total).toBe(3); - expect(stats.pending).toBe(2); - expect(stats.completed).toBe(1); - - // Wait for all remaining - await wait(100); - - stats = await reminderClient.getStats(); - expect(stats.total).toBe(3); - expect(stats.pending).toBe(0); - expect(stats.completed).toBe(3); - }); -}); diff --git a/vendor/actors/examples/scheduling/vitest.config.ts b/vendor/actors/examples/scheduling/vitest.config.ts deleted file mode 100644 index 5bdee002..00000000 --- a/vendor/actors/examples/scheduling/vitest.config.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { defineConfig } from "vitest/config"; - -export default defineConfig({ - test: { - include: ["tests/**/*.test.ts"], - }, -}); diff --git a/vendor/actors/examples/workflow-sdk/.env.example b/vendor/actors/examples/workflow-sdk/.env.example deleted file mode 100644 index 084e37cc..00000000 --- a/vendor/actors/examples/workflow-sdk/.env.example +++ /dev/null @@ -1,5 +0,0 @@ -WORKFLOW_TARGET_WORLD=@rivet-dev/workflow-world -WORKFLOW_RUNTIME_URL=http://127.0.0.1:3000 - -# The Rivet connection uses the standard RivetKit environment variables. Local -# development needs none of them. diff --git a/vendor/actors/examples/workflow-sdk/package.json b/vendor/actors/examples/workflow-sdk/package.json index 9833a95e..f5d3e00c 100644 --- a/vendor/actors/examples/workflow-sdk/package.json +++ b/vendor/actors/examples/workflow-sdk/package.json @@ -6,8 +6,7 @@ "scripts": { "build": "nitro build", "check-types": "tsc --noEmit", - "dev": "nitro dev", - "test": "RIVET_RUN_ENGINE_PORT=16420 RIVETKIT_STORAGE_PATH=$PWD/.workflow-data vitest --config vitest.integration.config.ts run" + "dev": "nitro dev" }, "dependencies": { "@rivet-dev/workflow-world": "workspace:*", @@ -18,17 +17,21 @@ }, "devDependencies": { "@types/node": "^24.0.0", - "@workflow/vitest": "5.0.0-beta.35", "typescript": "^5.9.3", - "vite": "^7.0.0", - "vitest": "^4.1.9" + "vite": "^7.0.0" }, "engines": { "node": ">=22.0.0" }, "template": { - "technologies": ["typescript", "workflow-sdk"], - "tags": ["workflow", "durable"], + "technologies": [ + "typescript", + "workflow-sdk" + ], + "tags": [ + "workflow", + "durable" + ], "noFrontend": true, "skipVercel": true }, diff --git a/vendor/actors/examples/workflow-sdk/vitest.integration.config.ts b/vendor/actors/examples/workflow-sdk/vitest.integration.config.ts deleted file mode 100644 index a10370c8..00000000 --- a/vendor/actors/examples/workflow-sdk/vitest.integration.config.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { workflow } from "@workflow/vitest"; -import { defineConfig } from "vitest/config"; - -export default defineConfig({ - plugins: [workflow()], - test: { - include: ["workflows/**/*.integration.test.ts"], - setupFiles: ["./vitest.setup.ts"], - testTimeout: 60_000, - }, -}); diff --git a/vendor/actors/examples/workflow-sdk/vitest.setup.ts b/vendor/actors/examples/workflow-sdk/vitest.setup.ts deleted file mode 100644 index efd68fa8..00000000 --- a/vendor/actors/examples/workflow-sdk/vitest.setup.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { registry } from "@rivet-dev/workflow-world/registry"; -import { afterAll } from "vitest"; - -registry.config.shutdown = { - disableSignalHandlers: true, - gracePeriodMs: 1_000, -}; -afterAll(async () => { - await registry.shutdown(); -}); diff --git a/vendor/actors/examples/workflow-sdk/workflows/order.integration.test.ts b/vendor/actors/examples/workflow-sdk/workflows/order.integration.test.ts deleted file mode 100644 index c7b66904..00000000 --- a/vendor/actors/examples/workflow-sdk/workflows/order.integration.test.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { waitForSleep } from "@workflow/vitest"; -import { expect, test } from "vitest"; -import { getRun, start } from "workflow/api"; - -import { processOrder } from "./order.ts"; - -test("runs the workflow end to end", async () => { - const run = await start(processOrder, ["42"]); - const sleepId = await waitForSleep(run); - - await getRun(run.runId).wakeUp({ correlationIds: [sleepId] }); - - await expect(run.returnValue).resolves.toEqual({ - id: "42", - reservationId: "reservation-42", - status: "charged", - }); - expect(await run.status).toBe("completed"); -}); diff --git a/vendor/actors/rivetkit-typescript/artifacts/registry-config.json b/vendor/actors/rivetkit-typescript/artifacts/registry-config.json index 43753175..53173543 100644 --- a/vendor/actors/rivetkit-typescript/artifacts/registry-config.json +++ b/vendor/actors/rivetkit-typescript/artifacts/registry-config.json @@ -22,6 +22,21 @@ "description": "Disable the welcome message on startup. Default: false", "type": "boolean" }, + "sqlite": { + "description": "SQLite runtime configuration.", + "type": "object", + "properties": { + "backend": { + "description": "SQLite backend to use. Native defaults to local. Wasm defaults to remote and cannot use local.", + "type": "string", + "enum": [ + "local", + "remote" + ] + } + }, + "additionalProperties": false + }, "logging": { "description": "Logging configuration.", "type": "object", @@ -88,16 +103,20 @@ "description": "Version of the local engine package to use. Defaults to the current RivetKit version.", "type": "string" }, + "startServices": { + "description": "Starts Services when RivetKit manages a local Engine. Enabled by default for a managed local Engine. Set RIVET_RUN_SERVICES=0 or startServices: false to disable.", + "type": "boolean" + }, "configurePool": { - "description": "Automatically configure serverless runners in the engine.", + "description": "Automatically configure serverless nodes in the engine.", "type": "object", "properties": { "name": { - "description": "Name of the runner pool.", + "description": "Name of the node pool.", "type": "string" }, "url": { - "description": "URL of the serverless platform to configure runners.", + "description": "URL of the serverless platform to configure nodes.", "type": "string" }, "headers": { @@ -131,7 +150,7 @@ "type": "number" }, "drainOnVersionUpgrade": { - "description": "Drain runners when a new version is deployed. Defaults to true.", + "description": "Drain nodes when a new version is deployed. Defaults to true.", "type": "boolean" } }, @@ -149,7 +168,7 @@ "type": "string" }, "maxStartPayloadBytes": { - "description": "Maximum POST /start body size in bytes. Default: 1048576", + "description": "Maximum POST /start body size in bytes. Default: 16777216", "type": "number" }, "publicEndpoint": { @@ -163,8 +182,8 @@ }, "additionalProperties": false }, - "envoy": { - "description": "Configuration for envoy mode.", + "node": { + "description": "Configuration for node mode.", "type": "object", "properties": { "totalSlots": { @@ -172,15 +191,15 @@ "type": "number" }, "poolName": { - "description": "Name of this envoy pool. Default: 'default'", + "description": "Name of this node pool. Default: 'default'", "type": "string" }, - "envoyKey": { - "description": "Deprecated. Authentication key for the envoy.", + "nodeKey": { + "description": "Deprecated. Authentication key for the node.", "type": "string" }, "version": { - "description": "Version number of this envoy. Default: 1", + "description": "Version number of this node. Default: 1", "type": "number" } }, diff --git a/vendor/actors/rivetkit-typescript/packages/rivetkit/package.json b/vendor/actors/rivetkit-typescript/packages/rivetkit/package.json index 6d8d73ab..98e04543 100644 --- a/vendor/actors/rivetkit-typescript/packages/rivetkit/package.json +++ b/vendor/actors/rivetkit-typescript/packages/rivetkit/package.json @@ -1,6 +1,6 @@ { "name": "rivetkit", - "version": "2.3.31", + "version": "3.0.1", "description": "Lightweight libraries for building stateful actors on edge platforms", "license": "Apache-2.0", "keywords": [ @@ -210,7 +210,6 @@ "dependencies": { "@hono/zod-openapi": "^1.1.5", "@opentelemetry/api": "^1.1.0", - "@rivet-dev/services": "^0.2.3", "@rivetkit/bare-ts": "^0.6.2", "@rivetkit/engine-api-full": "workspace:*", "@rivetkit/engine-cli": "workspace:*", @@ -249,6 +248,9 @@ "vitest": "^3.1.1", "ws": "^8.18.1" }, + "optionalDependencies": { + "@rivet-dev/services": "^0.2.5" + }, "peerDependencies": { "drizzle-kit": "^0.31.2", "eventsource": "^4.0.0", From d844e697a0b0ad85ff480d82fee4812c9cb05b74 Mon Sep 17 00:00:00 2001 From: "rivet-docs-sync[bot]" Date: Tue, 3 Nov 2026 23:10:19 +0000 Subject: [PATCH 3/5] docs(docs): sync from rivet-dev/rivet@7aa2b2f --- vendor/docs/docs/content/architecture.mdx | 50 +- vendor/docs/docs/content/authentication.mdx | 16 +- vendor/docs/docs/content/benchmarking.mdx | 24 +- vendor/docs/docs/content/cli.mdx | 230 +- vendor/docs/docs/content/connect.mdx | 40 +- vendor/docs/docs/content/debugging.mdx | 22 +- vendor/docs/docs/content/endpoints.mdx | 70 + .../docs/content/environment-variables.mdx | 8 +- vendor/docs/docs/content/jwt.mdx | 90 +- vendor/docs/docs/content/namespaces.mdx | 14 +- vendor/docs/docs/content/nodes.mdx | 2 + .../docs/docs/content/pool-configuration.mdx | 69 + vendor/docs/docs/content/regions.mdx | 23 + vendor/docs/docs/content/statuses.mdx | 18 + vendor/docs/docs/content/troubleshooting.mdx | 83 + vendor/docs/docs/content/versions.mdx | 264 +- vendor/docs/docs/content/workers.mdx | 30 + vendor/docs/docs/sidebar.json | 72 +- .../docs/engine/artifacts/config-schema.json | 3046 +++++++++-------- .../actors-quickstart-next-js/registry.ts | 16 - .../{ => backend}/index.ts | 0 .../{ => frontend}/Counter.tsx | 6 +- .../actors-quickstart-react/frontend/main.tsx | 9 + .../actors-versions/programmatic-version.ts | 10 - .../docs/examples/docs/api/actors-destroy.ts | 2 +- .../examples/docs/api/actors-list-names.ts | 2 +- vendor/docs/examples/docs/api/actors-list.ts | 2 +- .../examples/docs/api/actors-reschedule.ts | 2 +- vendor/docs/examples/docs/api/actors-sleep.ts | 2 +- .../examples/docs/api/connection-actions.ts | 2 +- .../examples/docs/api/connection-connect.ts | 2 +- .../examples/docs/api/connection-errors.ts | 2 +- .../examples/docs/api/connection-events.ts | 2 +- .../docs/api/control-plane-datacenters.ts | 2 +- .../docs/api/control-plane-metadata.ts | 2 +- .../examples/docs/api/gateway-metadata.ts | 2 +- .../docs/examples/docs/api/gateway-queue.ts | 2 +- .../examples/docs/api/inspector-action.ts | 14 - .../docs/api/inspector-connections.ts | 7 - .../docs/api/inspector-database-execute.ts | 17 - .../docs/api/inspector-database-rows.ts | 12 - .../docs/api/inspector-database-schema.ts | 7 - .../docs/api/inspector-queue-delete.ts | 10 - .../examples/docs/api/inspector-queue-get.ts | 7 - .../examples/docs/api/inspector-queue-post.ts | 14 - .../docs/examples/docs/api/inspector-rpcs.ts | 7 - .../examples/docs/api/inspector-state-get.ts | 7 - .../docs/api/inspector-state-patch.ts | 14 - .../examples/docs/api/inspector-summary.ts | 7 - .../examples/docs/api/inspector-traces.ts | 7 - .../docs/api/inspector-workflow-history.ts | 7 - .../docs/api/inspector-workflow-replay.ts | 14 - .../examples/docs/api/namespaces-create.ts | 2 +- .../docs/examples/docs/api/namespaces-list.ts | 2 +- vendor/docs/examples/docs/api/pools-delete.ts | 16 + vendor/docs/examples/docs/api/pools-get.ts | 13 + .../examples/docs/api/pools-list-nodes.ts | 14 + ...{workers-configs-list.ts => pools-list.ts} | 8 +- ...kers-configs-upsert.ts => pools-upsert.ts} | 8 +- .../docs/examples/docs/api/tokens-inspect.ts | 2 +- .../docs/api/workers-configs-delete.ts | 13 - .../api/workers-configs-refresh-metadata.ts | 2 +- vendor/docs/examples/docs/api/workers-list.ts | 12 - .../api/workers-serverless-health-check.ts | 2 +- .../docs/cookbook-cron-jobs/daily-report.ts | 18 - .../examples/docs/durable-streams/client.ts | 14 + .../examples/docs/durable-streams/create.ts | 11 + .../examples/docs/durable-streams/producer.ts | 21 + .../docs/durable-streams/read-history.ts | 10 + .../docs/durable-streams/read-live.ts | 14 + .../examples/docs/durable-streams/write.ts | 13 + .../docs/examples/docs/general-edge/client.ts | 12 + .../docs/general-jwt/quickstart/client.ts | 2 +- .../examples/docs/onboarding-actors/client.ts | 20 + .../examples/docs/onboarding-actors/index.ts | 43 + vendor/docs/examples/docs/package.json | 4 +- vendor/docs/examples/docs/tsconfig.json | 9 +- 77 files changed, 2500 insertions(+), 2174 deletions(-) create mode 100644 vendor/docs/docs/content/endpoints.mdx create mode 100644 vendor/docs/docs/content/pool-configuration.mdx create mode 100644 vendor/docs/docs/content/regions.mdx create mode 100644 vendor/docs/docs/content/statuses.mdx create mode 100644 vendor/docs/docs/content/troubleshooting.mdx create mode 100644 vendor/docs/docs/content/workers.mdx delete mode 100644 vendor/docs/examples/docs/actors-quickstart-next-js/registry.ts rename vendor/docs/examples/docs/actors-quickstart-react/{ => backend}/index.ts (100%) rename vendor/docs/examples/docs/actors-quickstart-react/{ => frontend}/Counter.tsx (85%) create mode 100644 vendor/docs/examples/docs/actors-quickstart-react/frontend/main.tsx delete mode 100644 vendor/docs/examples/docs/actors-versions/programmatic-version.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-action.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-connections.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-database-execute.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-database-rows.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-database-schema.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-queue-delete.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-queue-get.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-queue-post.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-rpcs.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-state-get.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-state-patch.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-summary.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-traces.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-workflow-history.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-workflow-replay.ts create mode 100644 vendor/docs/examples/docs/api/pools-delete.ts create mode 100644 vendor/docs/examples/docs/api/pools-get.ts create mode 100644 vendor/docs/examples/docs/api/pools-list-nodes.ts rename vendor/docs/examples/docs/api/{workers-configs-list.ts => pools-list.ts} (52%) rename vendor/docs/examples/docs/api/{workers-configs-upsert.ts => pools-upsert.ts} (59%) delete mode 100644 vendor/docs/examples/docs/api/workers-configs-delete.ts delete mode 100644 vendor/docs/examples/docs/api/workers-list.ts delete mode 100644 vendor/docs/examples/docs/cookbook-cron-jobs/daily-report.ts create mode 100644 vendor/docs/examples/docs/durable-streams/client.ts create mode 100644 vendor/docs/examples/docs/durable-streams/create.ts create mode 100644 vendor/docs/examples/docs/durable-streams/producer.ts create mode 100644 vendor/docs/examples/docs/durable-streams/read-history.ts create mode 100644 vendor/docs/examples/docs/durable-streams/read-live.ts create mode 100644 vendor/docs/examples/docs/durable-streams/write.ts create mode 100644 vendor/docs/examples/docs/general-edge/client.ts create mode 100644 vendor/docs/examples/docs/onboarding-actors/client.ts create mode 100644 vendor/docs/examples/docs/onboarding-actors/index.ts diff --git a/vendor/docs/docs/content/architecture.mdx b/vendor/docs/docs/content/architecture.mdx index f7a6e484..334a1240 100644 --- a/vendor/docs/docs/content/architecture.mdx +++ b/vendor/docs/docs/content/architecture.mdx @@ -4,38 +4,30 @@ description: "How object storage, the control plane, and nodes work together to skill: true --- -Rivet has three parts: **object storage** keeps Actor data, the **control plane** schedules Actors and routes requests, and **actor nodes** run your code. - - - - - BACKEND - - - Clients - Browsers, apps - - - Actor nodes - Your code - - - Control plane - Schedule, route, persist - - - Object storage - S3, GCS or Azure - - - - +Rivet has three parts: **object storage** keeps Actor data, the **control plane** schedules Actors and routes requests, and **nodes** run your code. + + + + + + + + + + + + Object storage + S3, GCS, or Azure + Control plane + Schedule, route, persist + Nodes + Your code -## Actor nodes +## Nodes -An actor node is a process running your app with the Rivet SDK, started with `registry.start()`. It opens an outbound connection to the control plane and hosts the Actors assigned to it. Nodes need no public URL or inbound port for Actor traffic. Add nodes when you need more capacity. +A node is a process running your app with the Rivet SDK, started with `registry.start()`. It opens an outbound connection to the control plane and hosts the Actors assigned to it. Nodes need no public URL or inbound port for Actor traffic. Add nodes when you need more capacity. ## Control plane @@ -55,4 +47,4 @@ A namespace separates Actors, keys, and node pools. For example, use `production ## Node pools -A node pool groups nodes by name within a namespace. Configure a pool before connecting nodes to it. A node joins the pool selected by `RIVET_POOL`, which defaults to `default`. For example, create a `gpu` pool for Actors that need GPUs alongside a `default` pool for the rest. See [Nodes & Node Pools](/docs/nodes). +A node pool groups nodes by name within a namespace. Configure a pool before connecting nodes to it. A node joins the pool selected by `RIVET_POOL`, which defaults to `default`. For example, create a `gpu` pool for Actors that need GPUs alongside a `default` pool for the rest. See [Node Pool Configuration](/docs/pool-configuration). diff --git a/vendor/docs/docs/content/authentication.mdx b/vendor/docs/docs/content/authentication.mdx index 2df9255e..eb24d290 100644 --- a/vendor/docs/docs/content/authentication.mdx +++ b/vendor/docs/docs/content/authentication.mdx @@ -1,15 +1,19 @@ --- title: "Authentication" -description: "The credentials the control plane accepts and where each one belongs." +description: "Choose credentials for a self-hosted control plane or Rivet Cloud." skill: true --- -The control plane checks credentials before serving management requests or routing Actor traffic. Application-level authorization still belongs in your Actor. See [Permissions](/actors/docs/permissions). +The control plane checks credentials before serving management requests or routing Actor traffic. Application-level authorization still belongs in your Actor. See [Authentication](/actors/docs/authentication). -## Credentials +## Self-hosted control plane -Your Rivet token is the `auth.admin_token` value in the control plane config. Your nodes and backend use it to connect, create namespaces, and manage node pools. Keep it server-side. +The configured `auth.admin_token` grants every operation in every namespace. Keep it in your backend or secret store. Use it to create namespaces and issue [scoped JWTs](/docs/jwt) for applications. -For browser clients, issue [scoped JWTs](/docs/jwt). A JWT grants access to one namespace and an explicit set of resources and operations, so give each client only the permissions it needs. +A JWT grants access to one namespace and an explicit set of resources and operations. Give browser clients only the permissions they need, and keep tokens that can register nodes or manage pools on your backend. -Pass credentials in `Authorization: Bearer `, or use an [endpoint URL](/docs/connect) such as `https://production:@rivet.mycompany.com`. +Pass credentials in `Authorization: Bearer `, or use an [endpoint URL](/docs/endpoints) such as `https://production:@rivet.mycompany.com`. + +## Rivet Cloud + +Get your namespace endpoints and credentials from the [Rivet Cloud dashboard](https://dashboard.rivet.dev). Keep secret credentials on your backend. See [Rivet Cloud](/docs/deploy/cloud/) for managed deployment and token settings. diff --git a/vendor/docs/docs/content/benchmarking.mdx b/vendor/docs/docs/content/benchmarking.mdx index 1fbba5a8..2d9a776f 100644 --- a/vendor/docs/docs/content/benchmarking.mdx +++ b/vendor/docs/docs/content/benchmarking.mdx @@ -17,7 +17,7 @@ These measurements come from the October 25, 2026 Rivet Actors benchmark. Use th | **Software** | Debian 13, Node.js 24, release builds | | **Object storage** | Azure Blob Storage in the same region, with locally redundant storage (LRS) | -Requests use plain HTTP inside the region over reused connections, with one request in flight. Create and wake requests have 20 ms gaps. Each row reports all successful samples from its condition, with nearest-rank percentiles and no trimming. All conditions below completed without errors. +Requests use plain HTTP inside the region over reused connections, with one request in flight. Create and wake requests have 20 ms gaps. The warm-read condition has 1,000 warmups; inserts run without gaps. Each row reports all successful samples from its condition, with nearest-rank percentiles and no trimming. All conditions below completed without errors. ## Results @@ -29,6 +29,12 @@ Milliseconds, p50 / p99. | **Wake** | 1,200 | 4.37 | 6.80 | Client send to full ping reply from a Rivet Actor asleep for at least 10 seconds. | | **Durable insert** | 1,200 | 0.69 | 0.80 | One 128-byte SQLite row inserted in autocommit mode. Timed around the query on the node, including the write to a majority of disks across zones. | | **Warm read** | 1,200 | 0.059 | 0.080 | A primary-key read of one 128-byte row from SQLite's memory cache, timed around the query. | +| **Random read after sleep, 50 MB database** | 1,200 | 1.33 | 100.1 | First random point read after at least 13 seconds asleep. Timed around the query, with two network page fetches. | +| **Random read after sleep, 1 GB database** | 1,024 | 41.8 | 168.4 | The same condition with three network page fetches. | + +The query interval includes the SQLite call, transport, and materializing the result on the node. It excludes the client's HTTP round trip. Full HTTP p50 is 0.59 ms for a warm read, 17.8 ms for the 50 MB read after sleep, and 61.6 ms for the 1 GB read after sleep, including wake time. + +The node reaches the control plane in its own zone for reads; durable writes require a cross-zone acknowledgement. Sleeping does not guarantee a cold object-storage read. This setup tests replicated writes across zones, but its LRS bucket does not test object-storage availability during a zone failure. ## Reproducing it @@ -36,19 +42,25 @@ Milliseconds, p50 / p99. -Run three control plane instances on VMs in three zones of one region, each on raw local NVMe, with a bucket in the same region. Follow the [VM](/docs/deploy/self-host/control-plane/vm/) guide. Kubernetes does not give pods raw NVMe, so it cannot reproduce these numbers. +Run three control plane instances in three zones of one region, each on local NVMe, with a bucket in the same region. Follow the [Kubernetes](/docs/deploy/self-host/control-plane/kubernetes/) or [VM](/docs/deploy/self-host/control-plane/vm/) guide. -Run one node in the first zone, with a Rivet Actor that has a `ping` action and a SQLite table, and a load generator on the same machine. See [Deploy nodes](/docs/deploy/self-host/nodes/). +Run one node in the first zone, with a Rivet Actor that has a `ping` action and a SQLite table, and a load generator on the same machine. See [Deploy nodes](/docs/deploy/self-host/workers/). + + + + + +For the warm-read condition, seed one 128-byte row and run 1,000 reads before recording samples. Keep startup and warmup measurements separate from measured requests. -Use the sample counts and pacing above, with a new key for each create. For wakes, explicitly sleep each Actor and wait at least 10 seconds. +Use the sample counts and pacing above, with a new key for each create. For wakes, explicitly sleep each Actor and wait at least 10 seconds. For random reads, seed 128-byte rows into databases of the stated sizes, sleep the Actors for at least 13 seconds, and verify each measured query fetches pages over the network. Record HTTP and query intervals separately. @@ -59,3 +71,7 @@ Sort the successful samples and take nearest-rank percentiles. Report the sample
+ +## Under load + +These latency results use one request at a time. Concurrent create workloads that overlapped mass teardown produced timeouts. Unpaced 10 MiB writes produced errors, and a seven-minute write run slowed substantially. Measure sustained throughput and error rates for your workload separately from these latency conditions. diff --git a/vendor/docs/docs/content/cli.mdx b/vendor/docs/docs/content/cli.mdx index d052b5b7..49e25177 100644 --- a/vendor/docs/docs/content/cli.mdx +++ b/vendor/docs/docs/content/cli.mdx @@ -1,10 +1,13 @@ --- title: "CLI" -description: "Use the optional Rivet CLI to deploy to a Rivet Cloud cluster, read its logs, and call the Rivet Cloud API." +seoTitle: "Rivet CLI" +description: "Use the optional Rivet CLI to deploy Rivet Actors to Rivet Cloud and manage Rivet Cloud projects and clusters." skill: true --- -The `rivet` CLI (`@rivetkit/cli`) is optional. It deploys your app to a [Rivet Cloud](/docs/deploy/cloud/) cluster. Run it with your package manager: +The `rivet` CLI (`@rivetkit/cli`) is optional. You only need it to deploy to Rivet Cloud with `rivet deploy` and to manage Rivet Cloud projects and clusters. + +Run it with your package runner: ```bash npx @rivetkit/cli @@ -13,27 +16,70 @@ npx @rivetkit/cli | Command | Description | | --- | --- | | `rivet login` | Sign in to Rivet Cloud in the browser. | -| `rivet link` | Link the current directory to a cluster. | -| `rivet deploy` | Build and deploy your app to a cluster. | -| `rivet cluster logs` | Read or follow a cluster's logs. | +| `rivet link` | Link the current directory to a project or cluster. | +| `rivet deploy` | Build and deploy the project to Rivet Cloud. | +| `rivet logs` | Read or follow a project's compute logs. | +| `rivet pool` | List or delete compute pools in a namespace. | +| `rivet cluster logs` | Read or follow a cluster's engine and runner logs. | | `rivet api` | Make an authenticated request to the Rivet Cloud API. | +| `rivet engine` | Run the bundled `rivet-engine` binary directly. | +| `rivet setup-ci` | Install the GitHub Actions deploy workflow. | +| `rivet token` | Mint a namespace-scoped token. | ## Signing in and linking -`rivet login` opens a browser to sign in and stores the session in `~/.rivet/credentials`, refreshing it as needed. Pass `--no-browser` to print the sign-in URL instead. `rivet logout` removes the session and `rivet whoami` shows the signed-in account and linked cluster. +`rivet login` opens a browser to sign in and stores the session in `~/.rivet/credentials`, refreshing it as needed. Pass `--no-browser` to print the sign-in URL instead. `rivet logout` removes the session and `rivet whoami` shows the signed-in account and linked project. ```bash rivet login +rivet link # pick an organization and project rivet link --org my-org --cluster my-cluster ``` -`rivet link` writes `.rivet/project.json` in the current directory, so later commands there default to that cluster. It prompts for anything not passed as a flag. `rivet unlink` removes the link. +`rivet link` writes `.rivet/project.json` in the current directory, so later commands there default to that project or cluster. It prompts for anything not passed as a flag. `rivet unlink` removes the link. -Every command resolves its token in this order: `--token`, `RIVET_CLOUD_TOKEN`, then the `rivet login` session. Use `--token` or `RIVET_CLOUD_TOKEN` in CI. `--cluster` (or `RIVET_CLUSTER`) selects the cluster, with `--org` (or `RIVET_ORG`) naming the organization it belongs to. `--cloud-api` points at a different Cloud API endpoint. +Every command that talks to Rivet Cloud resolves its token in this order: `--token`, `RIVET_CLOUD_TOKEN`, the `rivet login` session, then a token saved by an earlier `rivet deploy --token`. Use `--token` or `RIVET_CLOUD_TOKEN` in CI. The project comes from `--project` and `--org` (or `RIVET_PROJECT` and `RIVET_ORG`). Otherwise an API token names its own project, and a `rivet login` session uses the linked directory or prompts for one. `--cluster` (or `RIVET_CLUSTER`) selects a cluster instead, with `--org` naming the organization it belongs to. `--cloud-api` points at a different Cloud API endpoint. ## `rivet deploy` -The CLI builds the image, uploads it as a build, rolls the pool out to that build, and prints the build ID. +Builds and pushes your project's Docker image and upserts the managed pool, printing the dashboard URL. Deploys target the `default` pool unless you pass `--pool`; a new pool is created on first deploy. See [Deploying to Rivet Cloud](/docs/deploy/self-host/control-plane). + +```bash +rivet deploy +``` + +A token passed with `--token` is saved to `~/.rivet/credentials`, so later deploys can omit it. + +| Flag | Default | Description | +| --- | --- | --- | +| `--token` | env / credentials | Rivet Cloud API token. | +| `--namespace` | `production` | Cloud namespace. | +| `--pool` | `default` | Compute pool to deploy to. | +| `--project` / `--org` | from token | Override project/org. | +| `--dockerfile` | `Dockerfile` | Dockerfile to build. | +| `--build-context` | `.` | Docker build context. | +| `--env KEY=VAL` | — | Environment override, repeatable. | +| `--image` | project slug | Image repository name. | +| `--tag` | git short SHA | Image tag. | +| `--yes` | — | Skip prompts. | +| `--reuse-image` | — | Keep the pool's current image and skip the Docker build and push. Use it to change resources without a rebuild. | + +The pool's resources and scaling are set with these flags. Each one left out keeps its server-side default. + +| Flag | Server default | Description | +| --- | --- | --- | +| `--cpu` | `1` | vCPUs per actor: `1`, `2`, `4`, `8`, or a value from `0.08` to below `1` with at most two decimals. | +| `--memory` | `512Mi` | Memory per actor, from `512Mi` to `4Gi`. | +| `--min-scale` | `0` | Actors kept running, `0` to `100`. | +| `--max-scale` | `1` | Most actors to scale to, `1` to `5000`. | +| `--max-concurrent-actors` | `1000` | Most actors the pool runs at once, `1` to `50000`. | +| `--instance-request-concurrency` | `80` | Concurrent requests per actor instance, `1` to `500`. | +| `--drain-grace-period` | `1800` | Seconds a draining instance waits for its actors to finish, `5` to `3200`. | +| `--drain-on-version-upgrade` | `true` | Drain instances on the old version when a new one deploys. Pass `--drain-on-version-upgrade=false` to disable. | + +### Deploying to a cluster + +Pass `--cluster` to deploy to a cluster instead of a project. The CLI builds the image, uploads it as a build, rolls the pool out to that build, and prints the build ID. ```bash rivet deploy --cluster my-cluster --org my-org @@ -49,7 +95,7 @@ rivet deploy --cluster my-cluster --build | Flag | Default | Description | | --- | --- | --- | -| `--cluster` | `RIVET_CLUSTER` / linked cluster | Cluster to deploy to. | +| `--cluster` | `RIVET_CLUSTER` / linked cluster | Cluster to deploy to instead of a project. | | `--org` | `RIVET_ORG` / linked organization | Organization the cluster belongs to. | | `--region` | the cluster's only region | Region of the pool. Required when the cluster has several regions. | | `--pool` | `default` | Pool to roll out. | @@ -59,34 +105,7 @@ rivet deploy --cluster my-cluster --build | `--image` | cluster name | Image name recorded on the build. | | `--tag` | git short SHA | Image tag recorded on the build. | -The saved image must be 5 GiB or smaller. See [Actor Nodes](/docs/deploy/cloud/compute) for what the image needs. - -## `rivet cluster logs` - -Prints a cluster's most recent control plane and node logs, oldest first. `-f` keeps following new lines. `--source engine` selects control plane logs and `--source runner` selects node logs. - -```bash -rivet cluster logs --cluster my-cluster -rivet cluster logs --cluster my-cluster --severity error -n 50 -rivet cluster logs --cluster my-cluster --source runner --pool default --contains timeout -f -``` - -Each line shows its timestamp, severity, source, and message. This format is not stable; pass `--json` to print one JSON object per line with `id`, `timestamp`, `severity`, `message`, `source`, `runner_pool`, and `instance_id`. - -| Flag | Default | Description | -| --- | --- | --- | -| `--cluster` | `RIVET_CLUSTER` / linked cluster | Cluster to read. Required. | -| `--source` | both | `engine` for the control plane or `runner` for nodes. | -| `--pool` | all pools | Only this node pool's logs. Cannot be combined with `--source engine`. | -| `--severity` | all | Only lines at this severity or above: `trace`, `debug`, `info`, `warn`, `error`, or `fatal`. | -| `--contains` | none | Only lines containing this text, case-insensitive. | -| `-n`, `--limit` | `100` | Number of recent lines to print first, up to 1000. | -| `-f`, `--follow` | none | Keep printing new lines as they arrive. | -| `--before` | none | Page back: only lines older than this line `id` from `--json` output. | -| `--json` | none | Emit JSON lines instead of formatted output. | -| `--token`, `--org`, `--cloud-api` | none | Same as `rivet deploy`. | - -Lines can arrive up to a minute late, and `--follow` prints them when they do. +The saved image must be 5 GiB or smaller. `--namespace`, `--env`, `--reuse-image`, and the resource and scaling flags apply to projects only and are rejected for a cluster. `rivet pool`, `rivet logs`, and `rivet token` do not support clusters. Read a cluster's logs with [`rivet cluster logs`](#rivet-cluster-logs). ## `rivet api` @@ -98,7 +117,7 @@ rivet api '/v2/clusters/{cluster}/builds' rivet api '/v2/clusters/{cluster}/builds/' -X DELETE ``` -The path is sent as written. `rivet api /v2/openapi.json` lists every endpoint. `{cluster}` and `{org}` are filled from the matching flag or the linked directory. +The path is sent as written, so `/v2/...` paths reach API v2 and unprefixed paths reach API v1. Each API serves its OpenAPI spec, which lists every endpoint: `rivet api /v2/openapi.json` for API v2 and `rivet api /doc` for API v1. `{cluster}`, `{org}`, and `{project}` are filled from the matching flag or the linked directory. Fields become a JSON body, and the method defaults to `POST` when a body is given. With `-X GET`, fields are sent as query parameters. @@ -118,3 +137,136 @@ rivet api '/v2/clusters/{cluster}/regions/us-east4/runner-pools/default' -X PUT | `--token`, `--cloud-api` | Same as `rivet deploy`. | The command exits with a non-zero status when the API responds with an error, after printing the response body. + +## `rivet logs` + +Prints a project's compute logs for one pool, oldest first. `-f` follows new lines live. For a cluster, use [`rivet cluster logs`](#rivet-cluster-logs). + +```bash +rivet logs +rivet logs --pool workers --contains error -n 200 +rivet logs --region us-east4 -f +``` + +| Flag | Default | Description | +| --- | --- | --- | +| `--namespace` | `production` | Cloud namespace. | +| `--pool` | `default` | Compute pool. | +| `--region` | all | Regions to include, comma-separated. | +| `--contains` | — | Only lines containing this text, case-insensitive. | +| `-n`, `--limit` | `100` | Number of history lines. Ignored with `--follow`. | +| `-f`, `--follow` | — | Keep printing new lines as they arrive. | +| `--before` | — | Page back: only lines before this ISO 8601 timestamp. | +| `--json` | — | Emit JSON lines instead of formatted output. | +| `--token`, `--project`, `--org` | — | See [Signing in and linking](#signing-in-and-linking). | + +## `rivet pool` + +Manages the compute pools in a namespace. A namespace can hold multiple pools; `default` is the one used when a `deploy` or `logs` command omits `--pool`. + +### `rivet pool list` + +```bash +rivet pool list +``` + +Each pool is printed as a status line (colorized by status) followed by its config (display name, image, resources, environment) and any error. Colors are disabled when stdout is not a terminal or `NO_COLOR` is set. This human-readable format is not stable; pass `--json` for machine-readable output. + +| Flag | Default | Description | +| --- | --- | --- | +| `--token` | env / credentials | Rivet Cloud API token. | +| `--namespace` | `production` | Cloud namespace. | +| `--project` / `--org` | from token | Override project/org. | +| `--json` | — | Emit raw JSON instead of formatted output. | +| `--with-env-vars` | — | Include environment variable values, which are secret and omitted otherwise. | + +### `rivet pool delete` + +Tears down a compute pool, then waits until it is fully removed, printing status changes as it goes. Prompts for confirmation unless `--yes` is passed, and refuses to run without confirmation when stdin is not a terminal. + +```bash +rivet pool delete --yes +``` + +| Flag | Default | Description | +| --- | --- | --- | +| `--namespace` | `production` | Cloud namespace the pool belongs to. | +| `--yes` | — | Skip the confirmation prompt. | +| `--token` | env / credentials | Rivet Cloud API token. | +| `--project` / `--org` | from token | Override project/org. | + +## `rivet cluster logs` + +Prints a cluster's most recent engine and runner logs, oldest first. `-f` keeps following new lines. Use `rivet logs` for a project's logs instead. + +```bash +rivet cluster logs --cluster my-cluster +rivet cluster logs --cluster my-cluster --severity error -n 50 +rivet cluster logs --cluster my-cluster --source runner --pool default --contains timeout -f +``` + +Each line shows its timestamp, severity, source (`engine`, or `runner/`), and message. This format is not stable; pass `--json` to print one JSON object per line with `id`, `timestamp`, `severity`, `message`, `source`, `runner_pool`, and `instance_id`. + +| Flag | Default | Description | +| --- | --- | --- | +| `--cluster` | `RIVET_CLUSTER` / linked cluster | Cluster to read. Required. | +| `--source` | both | `engine` or `runner`. | +| `--pool` | all pools | Only this runner pool's logs. Cannot be combined with `--source engine`. | +| `--severity` | all | Only lines at this severity or above: `trace`, `debug`, `info`, `warn`, `error`, or `fatal`. | +| `--contains` | — | Only lines containing this text, case-insensitive. | +| `-n`, `--limit` | `100` | Number of recent lines to print first, up to 1000. | +| `-f`, `--follow` | — | Keep printing new lines as they arrive. | +| `--before` | — | Page back: only lines older than this line `id` from `--json` output. | +| `--json` | — | Emit JSON lines instead of formatted output. | +| `--token`, `--org`, `--cloud-api` | — | Same as `rivet deploy`. | + +Lines can arrive up to a minute late, and `--follow` prints them when they do. + +## `rivet engine` + +Runs the bundled `rivet-engine` binary directly. Arguments are forwarded verbatim. + +```bash +rivet engine nuke # wipe local engine state +rivet engine wf list # inspect workflows +``` + +## `rivet setup-ci` + +Installs `.github/workflows/rivet-deploy.yml`, which deploys to Rivet Cloud on push and pull request. Add `--force` to overwrite. Then set the token secret: + +```bash +gh secret set RIVET_CLOUD_TOKEN +``` + +## `rivet token` + +Mints a namespace-scoped token for connecting to Rivet. Only the token is printed to stdout, so it can be captured directly by scripts (e.g. `TOKEN=$(rivet token create --kind secret)`). + +```bash +rivet token create --kind secret +``` + +| `--kind` | Prefix | Use | +| --- | --- | --- | +| `secret` | `sk_` | Server-side runner/runtime token. | +| `public` | `pk_` | Client token: resolve and manage actors. | +| `connection` | `ck_` | Client token limited to resolving actors and opening connections. | + +By default the namespace must already exist. Pass `--create-namespace` to create it first (useful for per-branch CI namespaces). + +| Flag | Default | Description | +| --- | --- | --- | +| `--kind` | _(required)_ | Token kind: `secret`, `public`, or `connection`. | +| `--namespace` | `production` | Cloud namespace. | +| `--create-namespace` | — | Create the namespace if it does not exist. | +| `--token` | env / credentials | Rivet Cloud API token. | +| `--project` / `--org` | from token | Override project/org. | + +## Engine binary resolution + +`rivet engine` resolves the `rivet-engine` binary from, in order: `--engine-binary`, `RIVET_ENGINE_BINARY_PATH`, a binary bundled next to the CLI, a local `target/{debug,release}` build, then an auto-downloaded release. Set `RIVETKIT_ENGINE_AUTO_DOWNLOAD=0` to require a local binary. + +## Related + +- [Deploying to Rivet Cloud](/docs/deploy/self-host/control-plane) diff --git a/vendor/docs/docs/content/connect.mdx b/vendor/docs/docs/content/connect.mdx index e71e630b..b6024eae 100644 --- a/vendor/docs/docs/content/connect.mdx +++ b/vendor/docs/docs/content/connect.mdx @@ -8,11 +8,31 @@ skill: true No configuration is needed. RivetKit runs a local control plane on your machine. -## Production +RivetKit runs Rivet Actors entirely on your machine. Configure `RIVET_ENDPOINT` when connecting to a separate control plane. ### Private endpoint -The private endpoint tells your nodes and backend where the control plane is. It carries a secret token, so keep it server-side. +Everything that talks to Rivet is configured with one URL, the Rivet endpoint. It carries three pieces of information: + +``` +https://:@api.rivet.dev +``` + +- **Host**: The control plane to connect to. Rivet Cloud is `api.rivet.dev`. Self-hosted deployments use their own host. +- **Namespace**: The isolated environment your Actors live in, such as `production` or `staging`. See [Namespaces](/docs/namespaces). +- **Token**: Authenticates the connection and scopes it to that namespace. The token prefix tells you where it is safe to use: + +| Prefix | Kind | Where it lives | +| --- | --- | --- | +| `sk_` | Secret | Your backend and workers only. Full access to the namespace. | +| `pk_` | Public | Browsers and mobile apps. Can resolve, create, and connect to Actors. | +| `ck_` | Connection | Browsers and mobile apps. Can only resolve Actors and open connections. | + +Create tokens in the dashboard under your namespace. + +## Connect Your Backend + +Set `RIVET_ENDPOINT` with a secret token wherever your workers run. This is the only setting most deployments need. @@ -34,13 +54,13 @@ RIVET_ENDPOINT=https://my-namespace:@rivet.example.com ## URL auth syntax -Endpoint URLs carry the namespace and token: +Clients reach your Actors through the control plane's gateway, never through your backend directly. Point them at the same endpoint with a public token instead of a secret one. -``` -https://namespace:token@host/path -``` +Pass the public endpoint directly when constructing a [JavaScript](/actors/docs/clients/javascript), [React](/actors/docs/clients/react), [Swift](/actors/docs/clients/swift), or [Rust](/actors/docs/clients/rust) client. + +## URL Auth Syntax -This is the recommended form. Alternatively, set them separately: +Embedding the namespace and token in the URL is the recommended form because it is one value to manage. If your platform cannot store credentials inside a URL, the same three values can be set separately: ```bash RIVET_ENDPOINT=https://rivet.example.com @@ -48,7 +68,11 @@ RIVET_NAMESPACE=my-namespace RIVET_TOKEN= ``` -On a self-hosted control plane, use your [namespace slug](/docs/namespaces) and your Rivet token, the `auth.admin_token` value from the control plane config. For the `default` namespace: `https://default:@rivet.example.com`. +| Environment Variable | Config Option | Description | +| --- | --- | --- | +| `RIVET_ENDPOINT` | `endpoint` | Control plane URL for your backend | +| `RIVET_NAMESPACE` | `namespace` | Namespace to run Actors in | +| `RIVET_TOKEN` | `token` | Token for the backend connection | ## Reference diff --git a/vendor/docs/docs/content/debugging.mdx b/vendor/docs/docs/content/debugging.mdx index e8fc9cb3..470f2b6a 100644 --- a/vendor/docs/docs/content/debugging.mdx +++ b/vendor/docs/docs/content/debugging.mdx @@ -18,7 +18,7 @@ export RIVET_TOKEN="" # export RIVET_API="http://localhost:6420" RIVET_NAMESPACE="default" RIVET_TOKEN="default" ``` -Send the token as a bearer token on every request except `GET /metadata`. Use a token authorized for the selected namespace. On a self-hosted control plane, your Rivet token works in every namespace. See [Namespaces](/docs/namespaces). +Send the token as a bearer token on every request except `GET /metadata`. Use a token authorized for the selected namespace. The self-hosted admin token can access every namespace. See [Namespaces](/docs/namespaces). ## Rivet Actors @@ -38,7 +38,7 @@ curl "$RIVET_API/actors?actor_ids=id1,id2&namespace=$RIVET_NAMESPACE" \ -H "Authorization: Bearer $RIVET_TOKEN" ``` -When `actor_ids` is set, `name` and `key` are ignored. +`actor_ids` cannot be combined with `name` or `key`. ```json { @@ -55,7 +55,7 @@ When `actor_ids` is set, `name` and `key` are ignored. } ``` -Keys in HTTP requests separate components with `/`, escaping `/` and `\` inside a component with a backslash. An empty component is `\0`. For example, the key `["chat", "42"]` is `chat/42`. Use `curl --get --data-urlencode` for keys containing special characters. The single-component key `my-key` needs no escaping. +Keys in HTTP requests use comma-separated components, with commas and backslashes escaped inside a component. Use `curl --get --data-urlencode` for keys containing special characters. The single-component key `my-key` needs no escaping. ### Create a Rivet Actor @@ -68,7 +68,9 @@ curl -X PUT "$RIVET_API/actors?namespace=$RIVET_NAMESPACE" \ -d '{ "name": "my-actor", "key": "my-key" }' ``` -The Rivet Actor runs in the `default` [node pool](/docs/nodes). +The Rivet Actor runs in the `default` node pool. + +Set `"pool": "gpu"` in the request body to select another configured [node pool](/docs/pool-configuration). ### Sleep or destroy a Rivet Actor @@ -85,7 +87,6 @@ curl -X DELETE "$RIVET_API/actors/{actor_id}?namespace=$RIVET_NAMESPACE" \ ```bash curl "$RIVET_API/actors/names?namespace=$RIVET_NAMESPACE" \ -H "Authorization: Bearer $RIVET_TOKEN" -``` ## Nodes @@ -99,8 +100,15 @@ curl "$RIVET_API/pools?namespace=$RIVET_NAMESPACE" \ -H "Authorization: Bearer $RIVET_TOKEN" ``` -Pool configuration persists even when no nodes are connected. See [Nodes & Node Pools](/docs/nodes#read-pools-and-nodes). +Pool configuration persists even when no nodes are connected. + +To check that nodes are connected, call a Rivet Actor from a client. A Rivet Actor stays **Pending** while no node in its node pool is connected. See [Statuses](/docs/statuses). + +## OpenAPI Spec + +An OpenAPI specification covering many of the management and actor endpoints is available: -## API reference +- In the repository at [`rivetkit-openapi/openapi.json`](https://github.com/rivet-dev/rivet/tree/main/rivetkit-openapi) +- Served at `/doc` when running locally Every control plane endpoint, with its parameters and responses, is listed in the [HTTP API reference](/docs/api). diff --git a/vendor/docs/docs/content/endpoints.mdx b/vendor/docs/docs/content/endpoints.mdx new file mode 100644 index 00000000..298cda4d --- /dev/null +++ b/vendor/docs/docs/content/endpoints.mdx @@ -0,0 +1,70 @@ +--- +title: "Endpoints" +description: "Tell your nodes and clients where the Rivet control plane is, with the namespace and token in one URL." +skill: true +--- + +## Local development + +No configuration is needed. RivetKit runs a local control plane on your machine. + +## Production + +### Private endpoint + +The private endpoint tells your nodes and backend where the control plane is. It carries a secret token, so keep it server-side. + + + + + +```bash +RIVET_ENDPOINT=https://my-namespace:sk_xxxxx@api.rivet.dev +``` + + + + + + + + + + + +### Public endpoint + +The public endpoint is what your app hands to browser clients. It is exposed to the internet, so use a public token (`pk_`), never a secret token (`sk_`). + +```bash +RIVET_PUBLIC_ENDPOINT=https://my-namespace:pk_xxxxx@api.rivet.dev +``` + + +## URL auth syntax + +Endpoint URLs carry the namespace and token: + +``` +https://namespace:token@host/path +``` + +This is the recommended form. Alternatively, set them separately: + +```bash +RIVET_ENDPOINT=https://api.rivet.dev +RIVET_NAMESPACE=my-namespace +RIVET_TOKEN=sk_xxxxx +``` + +On a self-hosted control plane, use your [namespace slug](/docs/namespaces) and admin token. For the `default` namespace: `https://default:@rivet.example.com`. + +## Reference + +| Environment Variable | Config Option | Description | +|---------------------|---------------|-------------| +| `RIVET_ENDPOINT` | `endpoint` | Control plane URL for your nodes and backend | +| `RIVET_NAMESPACE` | `namespace` | Namespace for Rivet Actor isolation | +| `RIVET_TOKEN` | `token` | Token for the control plane connection | +| `RIVET_PUBLIC_ENDPOINT` | | Client-facing endpoint | +| `RIVET_PUBLIC_TOKEN` | | Client-facing token | diff --git a/vendor/docs/docs/content/environment-variables.mdx b/vendor/docs/docs/content/environment-variables.mdx index 75a08495..e3665770 100644 --- a/vendor/docs/docs/content/environment-variables.mdx +++ b/vendor/docs/docs/content/environment-variables.mdx @@ -5,8 +5,7 @@ skill: true --- These variables wire your process to a Rivet control plane. Variables that -configure the RivetKit SDK itself, including logging, storage, and the -inspector, are listed in [Environment Variables](/actors/docs/environment-variables) +configure the RivetKit SDK itself, including logging and storage, are listed in [Environment Variables](/actors/docs/environment-variables) in the Actors docs. ## Connection @@ -22,8 +21,7 @@ in the Actors docs. | Environment Variable | Description | |---------------------|-------------| | `RIVET_POOL` | Node pool to join (default: "default"). See [Architecture](/docs/architecture#node-pools). | -| `RIVET_ENVOY_VERSION` | Version number of this node. Increase it on every deploy. See [Versions & Upgrades](/docs/versions#setting-the-version). | - +| `RIVET_NODE_VERSION` | Version number of this node (default: 1). Increase it on every deploy. `RIVET_ENVOY_VERSION` is still read as an older name. See [Versions & Upgrades](/docs/versions#setting-the-version). | ## Local Control Plane @@ -35,5 +33,5 @@ In development, RivetKit starts a local control plane for you. These variables o | `RIVET_RUN_ENGINE_HOST` | Host the local control plane binds to. Defaults to `127.0.0.1`. | | `RIVET_RUN_ENGINE_PORT` | Port the local control plane binds to. Defaults to `6420`. | | `RIVET_RUN_ENGINE_VERSION` | Version of the local control plane to download | -| `RIVET_RUN_SERVICES` | Set to `1` to run Services with the local control plane, or `0` to disable it. By default, Services runs whenever the local control plane does. | +| `RIVET_RUN_SERVICES` | Services starts by default when RivetKit manages a local Engine. Set to `0` to disable it. | | `RIVET_SERVICES_BINARY` | Path to a local `rivet-services` binary. | diff --git a/vendor/docs/docs/content/jwt.mdx b/vendor/docs/docs/content/jwt.mdx index 34c83bac..85b4d540 100644 --- a/vendor/docs/docs/content/jwt.mdx +++ b/vendor/docs/docs/content/jwt.mdx @@ -4,45 +4,21 @@ description: "Issue short-lived JWTs with explicit permissions in one namespace. skill: true --- -A scoped token is a JWT that gives its holder selected permissions in one namespace. Issue it on your backend with your Rivet token, using the RivetKit client or the HTTP API, then return only the scoped token to the application. +A scoped token gives its holder selected permissions in one namespace. Issue it on your backend with the control plane's admin credential, then return only the scoped token to the application. -## Issue a token +## Quickstart - - + + -Create a client on your backend with your Rivet token in the endpoint: - - - -For one Actor, call `issueToken` on its handle. Without `permissions`, the token can only send traffic to that Actor: - - - -Pass `permissions` to replace the default. The handle accepts `actor_gateway` and `actor` permissions and scopes each grant to the Actor's ID: - - - -For namespace-wide grants, such as creating Actors, call `client.auth.issueToken` with an explicit grant list: - - - -`expiresIn` is in seconds. `issuedAt` and `expiresAt` are Unix timestamps in milliseconds. - - - - -Call `POST /auth/tokens` with your Rivet token. This grants traffic to every Actor in the `production` namespace; use `{"id":""}` as the target for one Actor. +This example grants read access to Actor traffic in the `production` namespace. Every holder can reach every Actor in that namespace; use a specific Actor ID for private per-user access. ```bash -export RIVET_API=https://rivet.example.com - curl -X POST "$RIVET_API/auth/tokens" \ - -H "Authorization: Bearer $RIVET_TOKEN" \ + -H "Authorization: Bearer $RIVET_ADMIN_TOKEN" \ -H 'Content-Type: application/json' \ -d '{ "namespace": "production", - "subject": "user-123", "duration": 900, "grants": [ {"resource":"actor_gateway","target":"any","operations":["read"]} @@ -50,36 +26,22 @@ curl -X POST "$RIVET_API/auth/tokens" \ }' ``` -The response contains `token`, `issued_ts` and `expires_ts`. Timestamps are Unix milliseconds; `duration` is seconds. See [Create token](/docs/api/tokens/create). - - - +The response contains `token`, `issued_ts`, and `expires_ts`. Timestamps are Unix milliseconds; `duration` is seconds. -Return only the scoped token to the client. Never send your Rivet token to a browser. + + -## Use the token - - - - -Give the browser client a `getToken` function that asks your backend for a token. The client calls it on first use and again when the token expires. - - - - - - -Send the token as a bearer token. This request reaches the Actor's [request handler](/actors/docs/request-handler): +Set `$RIVET_TOKEN` to the returned token and call an Actor's gateway endpoint: ```bash -curl "$RIVET_API/gateway/$ACTOR_ID/request/" \ - -H "Authorization: Bearer $SCOPED_TOKEN" +curl "$RIVET_API/gateway/$ACTOR_ID/health" \ + -H "Authorization: Bearer $RIVET_TOKEN" ``` - - +This grant does not allow Actor creation, listing, node registration, or pool management. -A gateway grant does not allow Actor creation, listing, node registration or pool management. + + ## Grants @@ -92,29 +54,13 @@ Each grant names a `resource`, a `target`, and `operations` drawn from `create`, | `node` | Register or inspect nodes. | | `pool` | Read or manage node pool configuration. | -Actor management and gateway access require separate grants. Permission to reach one Actor does not allow the holder to create other Actors. Namespace administration and token issuance require your Rivet token. +Actor management and gateway access require separate grants. Permission to reach one Actor does not allow the holder to create other Actors. Namespace administration and token issuance require the admin credential. ## Inspect and renew ```bash curl "$RIVET_API/auth/tokens/inspect" \ - -H "Authorization: Bearer $SCOPED_TOKEN" -``` - -The response contains the namespace slug, grants, subject, and issue and expiry timestamps. Renew expiring credentials through your authenticated backend. Do not give clients your Rivet token to renew tokens themselves. - -## Signing keys - -The control plane signs tokens with keys it rotates automatically every 7 days. A token lasts 1 hour by default and at most 24 hours. - -To revoke every outstanding token at once, rotate the signing keys immediately. Run these on any control plane instance; they read the instance's configuration: - -```bash -rivet-engine depot jwt show -rivet-engine depot jwt emergency-rotate \ - --request-id \ - --expected-coordinator-epoch \ - --expected-ring-version + -H "Authorization: Bearer $RIVET_TOKEN" ``` -Every instance stops accepting the old tokens within 5 minutes. If the command's reply is lost, run `show` again and retry with the same request ID. +The response contains the namespace slug, grants, subject, and issue and expiry timestamps. Renew expiring credentials through your authenticated backend. Do not give clients the admin credential to renew tokens themselves. diff --git a/vendor/docs/docs/content/namespaces.mdx b/vendor/docs/docs/content/namespaces.mdx index 1d65b0f2..8c2763ea 100644 --- a/vendor/docs/docs/content/namespaces.mdx +++ b/vendor/docs/docs/content/namespaces.mdx @@ -11,11 +11,11 @@ A namespace separates Actors, Actor keys, and node pools on one control plane. E -Use your Rivet token, the `auth.admin_token` value from your control plane config: +Use your control plane's admin token: ```bash curl -X POST "$RIVET_API/namespaces" \ - -H "Authorization: Bearer $RIVET_TOKEN" \ + -H "Authorization: Bearer $RIVET_ADMIN_TOKEN" \ -H 'Content-Type: application/json' \ -d '{"name":"staging"}' ``` @@ -31,12 +31,12 @@ Create a pool in the namespace before connecting nodes: ```bash curl -X PUT "$RIVET_API/pools/default?namespace=staging" \ - -H "Authorization: Bearer $RIVET_TOKEN" \ + -H "Authorization: Bearer $RIVET_ADMIN_TOKEN" \ -H 'Content-Type: application/json' \ -d '{"metadata":{"environment":"staging"}}' ``` -See [Nodes & Node Pools](/docs/nodes) for pool settings. +See [Node Pool Configuration](/docs/pool-configuration) for pool settings. @@ -44,9 +44,11 @@ See [Nodes & Node Pools](/docs/nodes) for pool settings. Set the namespace slug in the node's private endpoint and start the registry with `registry.start()`: ```bash -RIVET_ENDPOINT=https://staging:@rivet.mycompany.com +RIVET_ENDPOINT=https://staging:@rivet.mycompany.com ``` +Use a [scoped token](/docs/deploy/self-host/control-plane/rbac/) for applications. The admin token can access every namespace. + @@ -54,7 +56,7 @@ RIVET_ENDPOINT=https://staging:@rivet.mycompany.com ```bash curl "$RIVET_API/namespaces?limit=100" \ - -H "Authorization: Bearer $RIVET_TOKEN" + -H "Authorization: Bearer $RIVET_ADMIN_TOKEN" ``` The response contains `namespaces` and `pagination.cursor`. Pass the cursor as `cursor` on the next request. Filter a single namespace with `?name=staging`. diff --git a/vendor/docs/docs/content/nodes.mdx b/vendor/docs/docs/content/nodes.mdx index aa8dfed9..135583d0 100644 --- a/vendor/docs/docs/content/nodes.mdx +++ b/vendor/docs/docs/content/nodes.mdx @@ -24,6 +24,8 @@ curl -X PUT "$RIVET_API/pools/default?namespace=$RIVET_NAMESPACE" \ The control plane refuses a node whose pool does not exist. Local development is the exception: when the endpoint is on `localhost`, RivetKit creates the pool itself. +If registration or a reconnect fails with `pool.not_found`, the node stops and reports its namespace and pool. A cached serverless runtime returns the same error and reports unhealthy until restarted. Check the configured namespace and pool, or restore the original control-plane storage before restarting the node. Recreating a pool does not restore lost Actor data. Transient connection failures still reconnect automatically. + diff --git a/vendor/docs/docs/content/pool-configuration.mdx b/vendor/docs/docs/content/pool-configuration.mdx new file mode 100644 index 00000000..58a92301 --- /dev/null +++ b/vendor/docs/docs/content/pool-configuration.mdx @@ -0,0 +1,69 @@ +--- +title: "Node Pool Configuration" +description: "Create persistent node pool configuration and connect nodes by pool name." +skill: true +--- + +A node pool groups nodes by name within a namespace. Configure the pool explicitly before connecting nodes to it. For example, use `default` for general workloads and `gpu` for Actors that need GPUs. + +## Quickstart + + + + +Set `$RIVET_API` to your control plane URL, `$RIVET_NAMESPACE` to the namespace slug, and `$RIVET_TOKEN` to a token with pool management access: + +```bash +curl -X PUT "$RIVET_API/pools/gpu?namespace=$RIVET_NAMESPACE" \ + -H "Authorization: Bearer $RIVET_TOKEN" \ + -H 'Content-Type: application/json' \ + -d '{"metadata":{"hardware":"gpu"}}' +``` + +Pool configuration persists independently of connected nodes. Repeating `PUT` updates the configuration. + + + + +Set the same namespace and pool on each node that should serve this workload: + +```bash +RIVET_ENDPOINT=https://staging:@rivet.mycompany.com +RIVET_POOL=gpu +``` + +Start your registry with `registry.start()`. Metadata describes the pool; it does not provision hardware. Run the nodes on the machines you want to use. + + + + +## Read configuration + +```bash +# One pool +curl "$RIVET_API/pools/gpu?namespace=$RIVET_NAMESPACE" \ + -H "Authorization: Bearer $RIVET_TOKEN" + +# All configured pools in the namespace +curl "$RIVET_API/pools?namespace=$RIVET_NAMESPACE" \ + -H "Authorization: Bearer $RIVET_TOKEN" +``` + +The single-pool response has a `pool` object. The list response has a `pools` array whose entries include their `name`, plus a `pagination.cursor` for the next page. A configured pool remains listed when no nodes are connected. + +## Remove a pool + +Stop its nodes before deleting its configuration: + +```bash +curl -X DELETE "$RIVET_API/pools/gpu?namespace=$RIVET_NAMESPACE" \ + -H "Authorization: Bearer $RIVET_TOKEN" +``` + +The control plane rejects deletion while nodes are connected. + +## Related + +- [Nodes](/docs/workers) +- [Namespaces](/docs/namespaces) +- [Deploy Nodes](/docs/deploy/self-host/workers/) diff --git a/vendor/docs/docs/content/regions.mdx b/vendor/docs/docs/content/regions.mdx new file mode 100644 index 00000000..09c5ab30 --- /dev/null +++ b/vendor/docs/docs/content/regions.mdx @@ -0,0 +1,23 @@ +--- +title: "Regions" +description: "Choose the region a Rivet Actor runs in on Rivet Cloud, and how regions work when you self-host." +skill: true +--- + +A Rivet Actor lives in one region for its lifetime, and its data stays in that region. + +## Region selection on Rivet Cloud + +By default, a Rivet Actor is created in the region nearest the client. Override the region at create time: + + + +See [Actor-Actor Communication](/actors/docs/communicating-between-actors) for the full set of create options. + +## Where a Rivet Actor stays + +A Rivet Actor does not move between regions. Reads and writes to its data never cross a region boundary. A call between Rivet Actors in different regions goes over the network, so treat it like any other remote call. + +## Self-hosting + +A self-hosted control plane runs in one region. Multi-region self-hosting is coming. diff --git a/vendor/docs/docs/content/statuses.mdx b/vendor/docs/docs/content/statuses.mdx new file mode 100644 index 00000000..b550e3b7 --- /dev/null +++ b/vendor/docs/docs/content/statuses.mdx @@ -0,0 +1,18 @@ +--- +title: "Actor Statuses" +description: "Understand the lifecycle statuses of Rivet Actors, what they mean, and how to troubleshoot common issues." +skill: true +--- + +## Statuses + +| Status | Description | +|---|---| +| **Starting** | The Rivet Actor has been created but is not yet accepting connections. | +| **Running** | The Rivet Actor is live and accepting connections. | +| **Sleeping** | The Rivet Actor went to sleep after a period of inactivity. It wakes automatically on the next request. | +| **Pending** | The Rivet Actor is waiting for a node. This happens when no node in its node pool is connected. See [Troubleshooting](/actors/docs/troubleshooting#actor-status-is-pending) for common causes. | +| **Crashed** | The Rivet Actor failed to start or hit a fatal error. See [Troubleshooting](/actors/docs/troubleshooting#actor-status-is-crashed) for common failure reasons. | +| **Destroyed** | The Rivet Actor was destroyed. | + +{/* TODO(code): document the status timestamps in the actor API (`create_ts` plus start, sleep and destroy times) once the control plane returns them. Today `GET /actors` returns only `create_ts`, and destroyed Rivet Actors are not listed. Also confirm whether "Crash Loop Backoff" still exists. */} diff --git a/vendor/docs/docs/content/troubleshooting.mdx b/vendor/docs/docs/content/troubleshooting.mdx new file mode 100644 index 00000000..33306bdc --- /dev/null +++ b/vendor/docs/docs/content/troubleshooting.mdx @@ -0,0 +1,83 @@ +--- +title: "Troubleshooting" +description: "Diagnose common Rivet Actors setup, connection, deployment, and runtime problems with targeted checks and corrective steps." +skill: true +--- + +## Common Steps + +Before diving into specific errors, try these general troubleshooting steps: + +- Check your server logs for `level=ERROR` or `level=WARN` messages. +- Check if any of your backend processes have crashed or restarted unexpectedly. +- If you need more diagnostics, set `RIVET_LOG_LEVEL=DEBUG` for verbose logging. See [Logging](/actors/docs/logging) for more options. + +## Persistent logs require durable object storage + +If startup reports `storage.log_directory requires durable object_storage.primary`, configure a durable primary object store. Setting `storage.log_directory` alone persists log shards, but cluster metadata and cold data live in `object_storage.primary`. Its default, `in_memory`, loses those objects when the control plane process exits. + +For a single control plane process, set `RIVET__OBJECT_STORAGE__PRIMARY__FILE_SYSTEM__PATH` to a directory on a persistent volume. Multiple control plane processes must share a durable object store such as S3, GCS, or Azure Blob Storage. See [Storage](/docs/deploy/self-host/control-plane/storage/). + +### Missing records after a restart + +If logs report `a volume has no stored record but a replica reports a cold position above zero` and requests fail with `depot.corrupt`, the primary object store is missing data that the surviving log shards expect. This can happen after restarting with an in-memory primary store, or after pointing an existing deployment at an empty store. + +Preserve the log directory and any remaining object storage before attempting recovery. If the original durable object store still exists, check its configured location, bucket or container, and prefix. Pointing at a new empty store does not recover existing data. Storage inspection and repair cannot reconstruct cold data that has already been lost and trimmed from the log shards. Contact support with the configuration and logs before changing stored data. + +## Reporting Issues + +If you're stuck, reach out on [Discord](https://rivet.dev/discord) or file an issue on [GitHub](https://github.com/rivet-dev/rivet/issues). + +When reporting, please include: + +- **Symptoms** + - Whether this is happening in local dev, deployed, or both + - The error you're seeing (screenshot or error message) + - Relevant source code related to the issue +- **What you've tried to solve it** +- **Environment** + - RivetKit version + - Runtime (Node, Bun, etc.) including version + - If applicable, hosting platform in use (e.g. Kubernetes, Railway, AWS ECS) + - If applicable, HTTP router in use (e.g. Hono, Express, Elysia) + +## Actor status is crashed + +See [Actor Statuses](/docs/statuses) for more about this status. + +The dashboard will show the specific failure reason. Common errors include: + +### `crashed` + +The actor's `run` handler threw an unhandled exception or exited unexpectedly. Check your actor logs for the error message and stack trace. + +{/* TODO(code): list the allocation failure reasons the control plane reports for a Rivet Actor once it records them. Today only a crash in your own code is reported. */} + +### `internal_error` + +An unexpected error occurred within Rivet. If this persists, please [contact support](https://rivet.dev/actors/docs). + +## Actors crashing immediately on startup + +If your actors are being created and then immediately destroyed or crashing, there is likely an error being thrown in your `createState` or `onCreate` lifecycle hooks. These hooks run during actor initialization before the actor is marked as ready. + +Check your server logs for the error message and stack trace. Common causes include: + +- An exception thrown in `createState` (e.g. invalid input, failed validation, or a runtime error when computing initial state) +- An exception thrown in `onCreate` (e.g. a failing external API call, missing configuration, or invalid setup logic) + +Fix the error in the relevant lifecycle hook and redeploy. + +## Actors not upgrading to new code + +During a rollout, old and new nodes both run Rivet Actors until the old nodes stop. A Rivet Actor started on an old node keeps running the old code until it sleeps or its node stops. Finish the rollout by stopping every old node. See [Versions & Upgrades](/docs/versions). + +## Actor status is pending + +See [Actor Statuses](/docs/statuses) for more about this status. + +An actor stays in "pending" status while no node in its node pool is connected to accept it. + +- Check that at least one node is running and that its `RIVET_ENDPOINT` points at the right control plane and namespace. +- Check that the node joined the node pool the actor runs in. A node joins the pool named by `RIVET_POOL`, or `default`. +- Check your node logs for connection errors. diff --git a/vendor/docs/docs/content/versions.mdx b/vendor/docs/docs/content/versions.mdx index 0da41316..e2120550 100644 --- a/vendor/docs/docs/content/versions.mdx +++ b/vendor/docs/docs/content/versions.mdx @@ -1,244 +1,25 @@ --- title: "Versions & Upgrades" -description: "Version node deployments, route new Rivet Actors to current code, and drain older nodes without downtime." +description: "Roll out new code to your nodes and upgrade Rivet Actor state without downtime." skill: true --- -## How Versions Work +## Rolling out a new version -Each node has a **version number**. When you deploy new code with a new version, Rivet handles the transition automatically: +Deploy new code by rolling your nodes like any other service. When a node stops, its Rivet Actors sleep and save their state, then wake on a running node on their next request. During the rollout, old and new nodes both run Rivet Actors, so keep each deploy compatible with the state the previous one wrote. See [Upgrading Actor State](#upgrading-actor-state). -- **New actors go to the newest version**: When allocating actors, Rivet always prefers nodes with the highest version number -- **Multiple versions can coexist**: Old actors continue running on old versions while new actors are created on the new version -- **Drain old actors**: When enabled, a node connecting with a newer version number gracefully stops old actors so they are rescheduled to the new version -- **Versions only go up**: Deploying a lower version number never moves allocation back to it. To undo a bad deploy, redeploy the previous code with a new, higher version number. +### Setting the version - -Versions are not configured by default. See [Setting the Version](#setting-the-version) to configure the node version. - +Set `RIVET_NODE_VERSION` to a number that increases on every deploy. Within a node pool, new and waking Rivet Actors are only placed on nodes running the newest version that has a connected node, so as soon as the first node of a deploy connects, the previous deploy stops receiving new actors. Actors already running on older nodes keep running until those nodes stop. A version whose nodes have all disconnected is ignored, so a failed deploy does not block placement. -### Example Scenario +Without `RIVET_NODE_VERSION`, every node reports version 1 and placement spreads across all connected nodes in the pool. The version of each node is shown in the node listing API as `version`. - +### Drain on version upgrade - +Placement alone leaves Rivet Actors that never sleep on the old nodes until those nodes stop. Set `drain_on_version_upgrade` on the pool to move them as well: once a node of a newer version is connected, actors on older nodes are stopped the same way a node shutdown stops them, and they wake on the newest version on their next request. Eviction starts after `actor_eviction_delay` seconds and is paced by `actor_eviction_period` and `actor_eviction_rate`, so a large pool is not rescheduled all at once. See [Pool settings](/docs/nodes#pool-settings). -When a new version is deployed, existing actors are gracefully stopped on the old node and rescheduled onto the new version. +The older nodes stay connected and keep receiving heartbeats, but no new actors are placed on them. Rivet never exits a node process; stopping or replacing the old nodes is up to whatever runs them. If every node of the newer version disconnects, the drain stops and the older nodes serve again. A pool's settings are read when a node connects, so changing them applies to nodes that connect afterwards. -
-
- - - - - - - Node v1 - - - Node v2 - - Currently running - - Deployed - - Drain old actors - - - Reschedule actors - - - Shut down when all actors stopped - -
-
- -
- - - -When a new version is deployed, both versions coexist. New actors are created on the new version while existing actors continue running on the old version until they sleep. - -
-
- - - - Node v1 - - - Node v2 - - Currently running - - Deployed - - Actor 1 sleeps from inactivity - - Actor 1 wakes up when prompted - -
-
- -
- -
- -## Configuration - -### Setting the Version - -Configure the node version with an environment variable or in your registry setup: - - - -```bash {{"title": "Environment Variable"}} -RIVET_ENVOY_VERSION=2 -``` - - - - - - -The version **must** be set at build time, not at runtime. Do not use `Date.now()` or similar runtime values in your registry setup code. This would assign a different version every time the server starts, causing actors to be drained and rescheduled on every restart instead of only on new deployments. - - - -The version **must** increase on every deployment. Never roll a deployment back to an older version number. New actors keep going to the nodes still on the higher version, so as the rollback replaces them the set of nodes accepting actors shrinks until it reaches zero and nothing can be scheduled. Allocation only recovers once every higher-version node has disconnected and expired. To undo a bad deploy, redeploy the previous code with a new, higher version number. - - -### Example Configurations - -We recommend injecting a build-time value that increments with every deployment. Here are concrete examples for common setups: - - - - - -Generate the version at build time and bake it into the image as an environment variable: - -```bash @nocheck -docker build --build-arg RIVET_ENVOY_VERSION=$(date +%s) . -``` - -```dockerfile @nocheck -FROM node:24-slim -ARG RIVET_ENVOY_VERSION -ENV RIVET_ENVOY_VERSION=$RIVET_ENVOY_VERSION -WORKDIR /app -COPY . . -RUN npm install && npm run build -CMD ["node", "dist/server.js"] -``` - -All containers from this image will share the same version. - - - - - -Set the version in `next.config.ts`. Next.js evaluates this file once at build time and inlines the value into the bundle: - -```typescript @nocheck -import type { NextConfig } from "next"; - -const nextConfig: NextConfig = { - env: { - RIVET_ENVOY_VERSION: String(Math.floor(Date.now() / 1000)), - }, -}; - -export default nextConfig; -``` - - - - - -Use `define` in your Vite config. This is evaluated once at build time and inlined into the bundle: - -```typescript @nocheck -import { defineConfig } from "vite"; - -export default defineConfig({ - define: { - "process.env.RIVET_ENVOY_VERSION": JSON.stringify( - String(Math.floor(Date.now() / 1000)) - ), - }, -}); -``` - - - - - -Set the version from your CI pipeline: - -```yaml @nocheck -# GitHub Actions -env: - RIVET_ENVOY_VERSION: ${{ github.run_number }} -``` - -```bash @nocheck -# Railway / Render / generic CI -export RIVET_ENVOY_VERSION=$(date +%s) -``` - -```bash @nocheck -# Git commit count -export RIVET_ENVOY_VERSION=$(git rev-list --count HEAD) -``` - - - - - -Generate a version file during your build step and import it: - -```json @nocheck -{ - "scripts": { - "build": "echo \"export const BUILD_VERSION = $(date +%s);\" > src/build-version.ts && tsc" - } -} -``` - -```typescript @nocheck -import { actor, setup } from "rivetkit"; -import { BUILD_VERSION } from "./build-version"; - -const myActor = actor({ state: {}, actions: {} }); - -const registry = setup({ - use: { myActor }, - envoy: { - version: BUILD_VERSION, - }, -}); -``` - - - - - -### Drain on Version Upgrade - -The `drain_on_version_upgrade` setting on a node pool controls whether old actors are stopped when nodes with a newer version connect. Set it when you create or update the pool. See [Nodes & Node Pools](/docs/nodes) for every pool setting, including how to rate-limit actor eviction during the drain. - -```bash -curl -X PUT "$RIVET_API/pools/default?namespace=default" \ - -H "Authorization: Bearer $RIVET_TOKEN" \ - -H 'Content-Type: application/json' \ - -d '{"drain_on_version_upgrade": true}' -``` - -| Value | Behavior | -|-------|----------| -| `false` (default) | Old actors keep running. New actors go to the new version. Versions coexist. | -| `true` | Old actors sleep, saving their state, and wake on a node running the new version. | ## Upgrading Actor State @@ -274,30 +55,11 @@ Use [Zod](https://zod.dev/) to parse persisted state on wake. Zod's `.default()` For anything beyond simple defaults, consider moving to [SQLite](/actors/docs/sqlite) where you get proper migration tooling. -## Advanced - -### How Version Upgrade Detection Works - -When `drain_on_version_upgrade` is enabled and a node connects with a newer version number, the control plane drains every older node in the same pool. - -### SIGTERM Handling - -When a node process receives `SIGTERM`, it gracefully stops all of its actors before exiting: - -- Each actor's `onSleep` hook runs, giving it time to save state. -- Actors are rescheduled to other available nodes. -- If the process is killed before its actors finish stopping, for example with `SIGKILL`, the control plane reschedules them once the node is considered lost. - -Give each node at least 60 seconds between `SIGTERM` and `SIGKILL`. - -### Shutdown Timeouts +## Stopping a node -| Timeout | Default | Description | Configuration | -|---------|---------|-------------|---------------| -| `sleepGracePeriod` | 15s | Total graceful sleep budget for `onSleep`, `waitUntil`, `keepAwake`, and async raw WebSocket handlers | [Actor options](/actors/docs/lifecycle#options) | -| `envoy_lost_threshold` | 40s | How long the control plane waits before rescheduling the actors of a node that disappeared without stopping | [Control plane config](/docs/deploy/self-host/control-plane/configuration/) (`pegboard.envoy_lost_threshold`) | +When a node receives `SIGTERM`, it puts each of its Rivet Actors to sleep before exiting. Each Rivet Actor gets up to 15 seconds to save its state. If a node disappears without stopping, the control plane reschedules its Rivet Actors after 15 seconds. ## Related -- [Nodes & Node Pools](/docs/nodes): Pool settings and connecting nodes -- [Lifecycle](/actors/docs/lifecycle): Actor lifecycle hooks including `onSleep` +- [Architecture](/docs/architecture) +- [Deploy nodes](/docs/deploy/self-host/workers/) diff --git a/vendor/docs/docs/content/workers.mdx b/vendor/docs/docs/content/workers.mdx new file mode 100644 index 00000000..463bda31 --- /dev/null +++ b/vendor/docs/docs/content/workers.mdx @@ -0,0 +1,30 @@ +--- +title: "Nodes" +description: "Run your registry as a node, select a node pool, and add capacity." +skill: true +--- + +A node is a long-running process running your app with the Rivet SDK. Start it with `registry.start()`. It connects outbound to the control plane and hosts the Actors assigned to it. + +## Connect a node + +Create a [namespace](/docs/namespaces) and [node pool](/docs/pool-configuration), then set the node's connection variables: + +```bash +RIVET_ENDPOINT=https://production:@rivet.mycompany.com +RIVET_POOL=default +``` + +`RIVET_POOL` defaults to `default`. The pool must be configured in the selected namespace before the node connects. + +Actor traffic uses the outbound connection, so nodes need no public URL or inbound port. Your app can expose its own [health and metrics routes](/actors/docs/http-server#add-health-and-metrics-routes). + +## Add capacity + +Run more copies of your app with the same namespace and pool. Use your hosting platform's autoscaler to change the number of node processes. Keep spare capacity so Actors can wake while another node restarts. + +When a node stops, its Actors sleep and can wake on another node in the pool. See [Versions & Upgrades](/docs/versions) for rolling deployments. + +## Deploy + +Use the shared [node deployment guides](/docs/deploy/self-host/workers/) for Kubernetes, Docker, virtual machines, and other platforms that run a persistent process. Nodes can connect to Rivet Cloud or a self-hosted control plane. diff --git a/vendor/docs/docs/sidebar.json b/vendor/docs/docs/sidebar.json index 24dd667a..e507a9da 100644 --- a/vendor/docs/docs/sidebar.json +++ b/vendor/docs/docs/sidebar.json @@ -15,15 +15,26 @@ ] }, { - "title": "Connect", + "title": "Running Workloads", "pages": [ { - "title": "Connect", - "href": "/docs/connect" + "title": "Namespaces", + "href": "/docs/namespaces" + }, + { + "title": "Nodes", + "href": "/docs/workers" + }, + { + "title": "Node Pool Configuration", + "href": "/docs/pool-configuration" + }, + { + "title": "Endpoints", + "href": "/docs/endpoints" }, { "title": "Authentication", - "collapsible": true, "pages": [ { "title": "Overview", @@ -33,60 +44,55 @@ "title": "Scoped Tokens", "href": "/docs/jwt" } - ] + ], + "collapsible": true + }, + { + "title": "Environment Variables", + "href": "/docs/environment-variables" + }, + { + "title": "Versions & Upgrades", + "href": "/docs/versions" + }, + { + "title": "Regions", + "href": "/docs/regions" } ] }, { - "title": "Operate", + "title": "Operating", "pages": [ { - "title": "Namespaces", - "href": "/docs/namespaces" + "title": "Statuses", + "href": "/docs/statuses" }, { - "title": "Nodes & Node Pools", - "href": "/docs/nodes" + "title": "Tracing", + "href": "/docs/tracing" }, { - "title": "Versions & Upgrades", - "href": "/docs/versions" + "title": "Debugging", + "href": "/docs/debugging" }, { - "title": "Monitoring", - "collapsible": true, - "pages": [ - { - "title": "OpenTelemetry", - "href": "/docs/tracing" - }, - { - "title": "Management API", - "href": "/docs/debugging" - } - ] + "title": "Troubleshooting", + "href": "/docs/troubleshooting" } ] }, { "title": "Reference", "pages": [ - { - "title": "Environment Variables", - "href": "/docs/environment-variables" - }, { "title": "CLI", "href": "/docs/cli" }, { - "title": "API Specs", + "title": "API Reference", "collapsible": true, "pages": [ - { - "title": "HTTP API", - "href": "/docs/api" - }, { "title": "OpenAPI", "href": "https://github.com/rivet-dev/rivet/tree/main/rivetkit-openapi", diff --git a/vendor/docs/engine/artifacts/config-schema.json b/vendor/docs/engine/artifacts/config-schema.json index 2cb4c431..77abed1f 100644 --- a/vendor/docs/engine/artifacts/config-schema.json +++ b/vendor/docs/engine/artifacts/config-schema.json @@ -20,28 +20,6 @@ "auth": { "$ref": "#/definitions/Auth" }, - "compute_gateway": { - "default": null, - "anyOf": [ - { - "$ref": "#/definitions/ComputeGateway" - }, - { - "type": "null" - } - ] - }, - "depot": { - "default": null, - "anyOf": [ - { - "$ref": "#/definitions/DepotConfig" - }, - { - "type": "null" - } - ] - }, "epoxy": { "default": null, "anyOf": [ @@ -75,17 +53,6 @@ } ] }, - "metadata": { - "default": null, - "anyOf": [ - { - "$ref": "#/definitions/Metadata" - }, - { - "type": "null" - } - ] - }, "metrics": { "default": { "hardware": { @@ -101,6 +68,17 @@ } ] }, + "migrate_from_v2": { + "default": null, + "anyOf": [ + { + "$ref": "#/definitions/MigrateFromV2" + }, + { + "type": "null" + } + ] + }, "object_storage": { "default": null, "anyOf": [ @@ -164,6 +142,17 @@ } ] }, + "storage": { + "default": null, + "anyOf": [ + { + "$ref": "#/definitions/StorageConfig" + }, + { + "type": "null" + } + ] + }, "telemetry": { "default": { "enabled": true @@ -189,7 +178,7 @@ "additionalProperties": false, "definitions": { "AlarmConfig": { - "description": "Optional overrides for the tablet frontier and worker-owned callback pool.", + "description": "Optional overrides for the partition frontier and worker-owned callback pool.", "type": "object", "properties": { "handler_timeout_ms": { @@ -448,7 +437,7 @@ "minimum": 0.0 }, "disk_cache_directory": { - "description": "Directory for the local disk cache of cold-store object parts. Defaults to `cold-cache` inside `depot.log_directory`. Its contents are disposable.", + "description": "Directory for the local disk cache of cold-store object parts. Defaults to `cold-cache` inside `storage.log_directory`. Its contents are disposable.", "type": [ "string", "null" @@ -462,7 +451,7 @@ ] }, "disk_cache_on_flush": { - "description": "Writes each SST a tablet flush uploads into the disk cache as well, so its first reads are local. Defaults to true.", + "description": "Writes each SST a partition flush uploads into the disk cache as well, so its first reads are local. Defaults to true.", "type": [ "boolean", "null" @@ -478,7 +467,7 @@ "minimum": 0.0 }, "l0_max_ssts": { - "description": "L0 SSTs a tablet database holds before SlateDB stalls memtable flushes until a compaction drains them. One compaction takes up to this many sources, so it drains a full L0 at once. Higher values absorb flush bursts at the cost of more SSTs per read. Defaults to 16.", + "description": "L0 SSTs a partition database holds before SlateDB stalls memtable flushes until a compaction drains them. One compaction takes up to this many sources, so it drains a full L0 at once. Higher values absorb flush bursts at the cost of more SSTs per read. Defaults to 16.", "type": [ "integer", "null" @@ -487,7 +476,7 @@ "minimum": 0.0 }, "max_concurrent_compactions": { - "description": "Concurrent compactions per tablet database. A worker maintaining more than 8 tablets runs one per database. Defaults to 2.", + "description": "Concurrent compactions per partition database. A worker maintaining more than 8 partitions runs one per database. Defaults to 2.", "type": [ "integer", "null" @@ -505,7 +494,7 @@ "minimum": 0.0 }, "unflushed_budget_bytes": { - "description": "Unflushed memtable bytes for the whole process, split evenly across the tablets this worker maintains (at most 512 MiB and at least 8 MiB per tablet). Defaults to 1 GiB.", + "description": "Unflushed memtable bytes for the whole process, split evenly across the partitions this worker maintains (at most 512 MiB and at least 8 MiB per partition). Defaults to 1 GiB.", "type": [ "integer", "null" @@ -517,7 +506,7 @@ "additionalProperties": false }, "CommandConcurrency": { - "description": "Maximum simultaneous handlers per pegboard command class on one storage worker. Each value is further capped by `depot.kv_commands.max_inflight_commands`.", + "description": "Maximum simultaneous handlers per pegboard command class on one storage worker. Each value is further capped by `storage.kv_commands.max_inflight_commands`.", "type": "object", "properties": { "actor": { @@ -530,7 +519,7 @@ "minimum": 0.0 }, "actor_event": { - "description": "Actor state machine events, including envoy lifecycle reports. Defaults to 256.", + "description": "Actor state machine events, including node lifecycle reports. Defaults to 256.", "type": [ "integer", "null" @@ -559,29 +548,6 @@ }, "additionalProperties": false }, - "ComputeGateway": { - "type": "object", - "required": [ - "auth_token", - "cloud_url" - ], - "properties": { - "auth_token": { - "description": "Token for authenticating with the Cloud API's internal route endpoint.", - "allOf": [ - { - "$ref": "#/definitions/Secret" - } - ] - }, - "cloud_url": { - "description": "URL of the Cloud API (e.g., \"https://cloud.rivet.dev/internal/route\")", - "type": "string", - "format": "uri" - } - }, - "additionalProperties": false - }, "Datacenter": { "type": "object", "required": [ @@ -653,233 +619,201 @@ } ] }, - "DepotConfig": { + "Epoxy": { + "description": "Epoxy runs in a single datacenter with fixed membership, so it has no settings yet. The section stays so multi-region settings have a home.", + "type": "object", + "additionalProperties": false + }, + "FileSystemObjectStoreConfig": { + "description": "A local directory used by one engine process at a time. Conditional writes are atomic only among requests of that process.", "type": "object", + "required": [ + "path" + ], "properties": { - "alarms": { - "description": "Bounded, deadline-driven volume alarm delivery.", - "default": { - "handler_timeout_ms": null, - "io_timeout_ms": null, - "max_callbacks": null, - "max_candidates": null, - "max_operations": null, - "page_size": null, - "retry_max_ms": null, - "retry_min_ms": null - }, - "allOf": [ - { - "$ref": "#/definitions/AlarmConfig" - } - ] - }, - "auto_provision_tablets": { - "description": "Creates this many tablets over this storage worker when the cluster has none, so a single-node engine serves actors without an operator. A restart finishes a run that stopped partway; tablets it did not start are left alone. Clusters with several storage workers leave it unset and run `depot tablet provision` instead.", - "type": [ - "integer", - "null" - ], + "path": { + "description": "Created when it does not exist.", + "type": "string" + } + }, + "additionalProperties": false + }, + "FilesystemConfig": { + "type": "object", + "properties": { + "max_cache_bytes": { + "description": "Bytes one filesystem's row cache may retain, a fairness ceiling inside `max_process_cache_bytes`.", + "default": 8388608, + "type": "integer", "format": "uint", "minimum": 0.0 }, - "balancing": { - "default": { - "destination_stability_ms": 60000, - "enabled": true, - "max_disk_probes": 4, - "missing_worker_ms": 120000, - "tablets_per_core": 2 - }, - "allOf": [ - { - "$ref": "#/definitions/TabletBalancingConfig" - } - ] - }, - "bulk_read_bytes_per_sec": { - "description": "Bytes per second that bulk runs may read across every tablet of this process, with a burst of a quarter second (at least 4 MiB). Bulk runs wait for their bytes; point reads never wait. Unset or 0 leaves bulk runs unpaced.", - "type": [ - "integer", - "null" - ], - "format": "uint64", + "max_conflict_window_bytes": { + "default": 4194304, + "type": "integer", + "format": "uint", "minimum": 0.0 }, - "bulk_read_cache_blocks": { - "description": "Whether SST blocks a bulk run fetches enter the shared block cache. Defaults to true; false keeps large scans from evicting other volumes' hot blocks.", - "type": [ - "boolean", - "null" - ] + "max_memory_bytes": { + "default": 67108864, + "type": "integer", + "format": "uint", + "minimum": 0.0 }, - "bulk_read_fetch_tasks": { - "description": "Concurrent SST block fetches inside one bulk run's scan. Defaults to 1; 0 is treated as 1.", - "type": [ - "integer", - "null" - ], + "max_operation_bytes": { + "default": 8388608, + "type": "integer", "format": "uint", "minimum": 0.0 }, - "bulk_read_min_chunks": { - "description": "Chunk runs of at least this many chunks (4 KiB each) are read with the bulk scan settings below, as a table scan's read-ahead windows are. Unset or 0 reads every run with the normal settings.", - "type": [ - "integer", - "null" - ], + "max_pending_commits": { + "default": 128, + "type": "integer", "format": "uint", "minimum": 0.0 }, - "checkpoints": { - "default": { - "max_named_checkpoints_per_volume": 64, - "retention": null - }, - "allOf": [ - { - "$ref": "#/definitions/CheckpointConfig" - } - ] + "max_process_cache_bytes": { + "description": "Bytes all filesystem row caches in one process may retain together.", + "default": 1073741824, + "type": "integer", + "format": "uint", + "minimum": 0.0 }, - "cold_store": { - "default": { - "block_cache_bytes": null, - "compacted_sst_bytes": null, - "disk_cache_bytes": null, - "disk_cache_directory": null, - "disk_cache_on_compaction": null, - "disk_cache_on_flush": null, - "disk_cache_part_bytes": null, - "l0_max_ssts": null, - "max_concurrent_compactions": null, - "meta_cache_bytes": null, - "unflushed_budget_bytes": null - }, - "allOf": [ - { - "$ref": "#/definitions/ColdStoreConfig" - } - ] + "max_snapshot_age_ms": { + "default": 30000, + "type": "integer", + "format": "uint64", + "minimum": 0.0 }, - "cold_store_compression": { - "description": "Codec for SlateDB SST blocks in the cold store; defaults to `lz4`. Each SST records its own codec, so changing it keeps existing SSTs readable.", - "anyOf": [ - { - "$ref": "#/definitions/ColdStoreCompression" - }, - { - "type": "null" - } - ] + "max_snapshots": { + "default": 128, + "type": "integer", + "format": "uint", + "minimum": 0.0 }, - "command_timeout_ms": { - "description": "Floor for every typed Depot command deadline, in milliseconds. Each command keeps its own default (5 seconds generic, 30 seconds for actor storage); when set, the larger of the two bounds both the client's retry budget and the maintainer's handler timeout. Unset keeps the per-command defaults.", - "type": [ - "integer", - "null" - ], + "max_transaction_age_ms": { + "default": 300000, + "type": "integer", "format": "uint64", "minimum": 0.0 }, - "coordinator_request_capacity": { - "description": "Exact coordinator subject capacity. Defaults to 256.", - "type": [ - "integer", - "null" - ], + "max_transaction_bytes": { + "description": "Maximum application bytes in one filesystem transaction.", + "default": 134217728, + "type": "integer", "format": "uint", "minimum": 0.0 }, - "durable_max_events_per_commit": { - "description": "Most events of one durable state machine applied in one commit. Events that arrive while a commit is in flight are grouped up to this bound. Defaults to 16.", - "type": [ - "integer", - "null" - ], - "format": "uint32", + "max_unapplied_bytes": { + "description": "Most payload bytes one opening may have admitted ahead of the newest position its partition's maintainer reported applied. A new write past it is refused with a retry hint before it is built, so a writer faster than the apply, as under a slow cold store or compaction, waits at admission instead of growing an unbounded backlog.", + "default": 268435456, + "type": "integer", + "format": "uint", "minimum": 0.0 }, - "endpoint_cache_capacity": { - "description": "Maximum cached endpoint hints, including missing workers. Defaults to 4096.", - "default": null, - "type": [ - "integer", - "null" - ], + "max_value_bytes": { + "default": 1048576, + "type": "integer", "format": "uint", "minimum": 0.0 }, - "filesystem": { - "default": { - "max_cache_bytes": 8388608, - "max_conflict_window_bytes": 4194304, - "max_memory_bytes": 67108864, - "max_operation_bytes": 8388608, - "max_pending_commits": 128, - "max_process_cache_bytes": 1073741824, - "max_snapshot_age_ms": 30000, - "max_snapshots": 128, - "max_transaction_age_ms": 300000, - "max_transaction_bytes": 134217728, - "max_unapplied_bytes": 268435456, - "max_value_bytes": 1048576, - "note_ttl_ms": 1000, - "request_timeout_ms": 30000 - }, - "allOf": [ + "note_ttl_ms": { + "description": "How long a write's overlay notes (\"this page is at this sequence\") outlive the write before the filesystem drops them and keeps their rows only as cache. A later miss on one of those rows reads it from the maintainer once it has applied the write. About ten times the usual apply latency.", + "default": 1000, + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "request_timeout_ms": { + "default": 30000, + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "ForkConfig": { + "description": "Global bounds for source hold cleanup and background cross-region copies.", + "type": "object", + "properties": { + "check_grace_ms": { + "description": "Minimum age before an unfinished fork's destination is checked.", + "default": 60000, + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "materialize_batch_chunks": { + "description": "Further bounded by the maintainer's row and byte budgets.", + "default": 1024, + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "max_concurrent_materializations": { + "default": 2, + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "GcsObjectStoreConfig": { + "description": "Google Cloud Storage; defaults to the adapter's application default credentials.", + "type": "object", + "required": [ + "bucket" + ], + "properties": { + "bucket": { + "type": "string" + }, + "prefix": { + "default": null, + "type": [ + "string", + "null" + ] + }, + "service_account_key": { + "description": "Optional JSON service account credential override.", + "default": null, + "anyOf": [ { - "$ref": "#/definitions/FilesystemConfig" + "$ref": "#/definitions/Secret" + }, + { + "type": "null" } ] - }, - "flush_piggyback_min_bytes": { - "description": "Unflushed applied bytes at which a volume joins a tablet flush another volume requested. Defaults to 16 KiB.", + } + }, + "additionalProperties": false + }, + "Guard": { + "type": "object", + "properties": { + "host": { + "description": "Host for HTTP traffic", "type": [ - "integer", + "string", "null" ], - "format": "uint64", - "minimum": 0.0 + "format": "ip" }, - "flush_stage_concurrency": { - "description": "Volume records whose old rows one tablet filesystem flush reads at once while it stages. Staging excludes every other store operation of the tablet. Defaults to 16.", + "port": { + "description": "Port for HTTP traffic", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint16", "minimum": 0.0 }, - "forks": { - "default": { - "check_grace_ms": 60000, - "materialize_batch_chunks": 1024, - "max_concurrent_materializations": 2 - }, - "allOf": [ - { - "$ref": "#/definitions/ForkConfig" - } - ] - }, - "heartbeat_gc": { - "description": "Background heartbeat reclamation; separate from membership lease expiration.", - "default": { - "batch_interval_ms": null, - "batch_size": null, - "batch_timeout_ms": null, - "delete_concurrency": null, - "pass_interval_ms": null, - "retention_ms": null - }, - "allOf": [ - { - "$ref": "#/definitions/HeartbeatGcConfig" - } - ] - }, - "idle_unload_after_ms": { + "route_auth_check_timeout_ms": { + "description": "Timeout for guard-owned route authorization checks in milliseconds.", "type": [ "integer", "null" @@ -887,28 +821,8 @@ "format": "uint64", "minimum": 0.0 }, - "kv_commands": { - "default": { - "evicted_idle_warn_ms": null, - "max_command_bytes": null, - "max_eviction_closes": null, - "max_inflight_command_bytes": null, - "max_inflight_commands": null, - "max_open_volumes": null, - "max_worker_open_volume_bytes": null, - "max_worker_open_volumes": null, - "request_capacity": null, - "short_idle_close_ms": null, - "volume_idle_close_ms": null - }, - "allOf": [ - { - "$ref": "#/definitions/KvCommandConfig" - } - ] - }, - "learning_deadline_ms": { - "description": "How long a tablet replica-set change may stay in Learning before the coordinator aborts it and the tablet returns to its old members. Defaults to one hour and must be at least 45 minutes. It counts from the phase's start, not from the learner's progress, so it must outlast the membership holder wait (15 minutes) plus the copy of the largest log suffix a learner may have to catch up.", + "route_compute_timeout_ms": { + "description": "Timeout for resolving compute routes in milliseconds.", "type": [ "integer", "null" @@ -916,113 +830,99 @@ "format": "uint64", "minimum": 0.0 }, - "log_client_inflight_per_worker": { - "description": "Log shard requests a client keeps in flight to one storage worker. Later requests queue and go out together as one batch when a slot frees. Defaults to 2.", + "route_pegboard_auth_check_timeout_ms": { + "description": "Timeout for pegboard actor route authorization checks in milliseconds.", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "log_directory": { - "description": "Existing directory owned by one storage process. Required when storage services start.", + "tcp_nodelay": { + "description": "Enables TCP_NODELAY on accepted Guard sockets. Defaults to true.\n\nGuard carries actor nodes' WebSockets and client WebSocket and HTTP traffic, where most writes are small frames. With Nagle's algorithm on, a small frame waits for the peer to acknowledge the previous one, and a peer that delays its ACK holds it for about 40 ms. That delay landed on every actor's first response.", "type": [ - "string", + "boolean", "null" ] }, - "log_request_capacity": { - "description": "Exact replica subject capacity, shared by local clients and the shard. Defaults to 2048.", + "websocket_keepalive_interval_ms": { + "description": "Interval in milliseconds at which Guard sends a ping frame on every client WebSocket. Keeps idle connections alive through proxies that close quiet WebSockets, such as Cloudflare's roughly 100 second idle timeout. Must be greater than 0. Defaults to 30000 ms.", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 - }, - "log_shard": { - "description": "Optional overrides for the shard's disk, memory and operation bounds.", - "default": { - "checkpoint_bytes": null, - "checkpoint_timeout_ms": null, - "disk_read_concurrency": null, - "inbox_capacity": null, - "manifest_refresh_timeout_ms": null, - "max_admission_wait_ms": null, - "max_append_admission_wait_ms": null, - "max_batch_bytes": null, - "max_disk_bytes": null, - "max_disk_reads": null, - "max_loaded_volume_bytes": null, - "max_loaded_volumes": null, - "max_memory_bytes": null, - "max_memory_requests": null, - "max_retained_payload_bytes": null, - "max_retained_payload_bytes_per_volume": null, - "max_write_bytes": null, - "overload_retry_after_ms": null, - "preallocate_segments": null, - "recovery_timeout_ms": null, - "release_idle_payloads_after_ms": null, - "remove_segments_timeout_ms": null, - "segment_bytes": null, - "write_to_cold_at_disk_percent": null, - "write_to_disk_timeout_ms": null - }, - "allOf": [ - { - "$ref": "#/definitions/LogShardConfig" - } + } + }, + "additionalProperties": false + }, + "HardwareMetrics": { + "description": "Configuration for host hardware metrics.", + "type": "object", + "properties": { + "disk_probe": { + "description": "Times sequential writes and fsyncs on each data directory once at startup, in the background. Defaults to true.", + "type": [ + "boolean", + "null" ] }, - "lookup_request_capacity": { - "description": "Concurrent topology endpoint lookups and heartbeat inspections admitted per process. Defaults to 128.", + "disk_probe_bytes": { + "description": "Bytes the probe writes sequentially to each data directory. The fsync phase writes a further 400 KiB. Defaults to 64 MiB; at most 1 GiB.", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 - }, - "maintainer_inbox_capacity": { - "description": "Queued events one tablet maintainer accepts before it rejects new requests as overloaded. Every volume open, read, apply and status notice for the tablet passes through it, so a burst of actor starts on one tablet needs room for several events per start. Must be positive. Defaults to 4096.", + } + }, + "additionalProperties": false + }, + "HeartbeatGcConfig": { + "description": "Optional overrides for topology's bounded heartbeat cleanup service, which runs under the storage owner's singleton election. Topology defines the resolved defaults.", + "type": "object", + "properties": { + "batch_interval_ms": { + "description": "Pause between the batches of one pass. Defaults to 10 seconds.", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint64", "minimum": 0.0 }, - "maintainer_max_loaded_volumes": { - "description": "Volumes one tablet maintainer holds loaded at once, before opens of more are refused as overloaded. A loaded volume costs about 1.8 KiB of maintainer heap, so the default of 500,000 holds under 1 GiB per tablet. Must be positive.", + "batch_size": { + "description": "LIST entries examined per batch, 1 to 1000. Defaults to 128.", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint", "minimum": 0.0 }, - "maintainer_max_queued_opens": { - "description": "Volume opens queued in one tablet maintainer's inbox, not yet taken by its runner, at which a new open is refused as overloaded at once instead of joining the inbox. Other inbox events do not count. Opens queued past this would mostly expire before admission. Must be positive. Defaults to 1024.", + "batch_timeout_ms": { + "description": "Time budget of one batch. Defaults to 2 seconds.", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint64", "minimum": 0.0 }, - "maintainer_max_requests": { - "description": "Client requests one tablet maintainer tracks at once before it rejects more as overloaded. Must be positive. Defaults to 1024.", + "delete_concurrency": { + "description": "Conditional deletes in flight per batch, 1 to `batch_size`. Defaults to 4.", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint", "minimum": 0.0 }, - "manifest_refresh_ms": { - "description": "Fallback interval for re-reading the tablet manifest. Routing misses and `NotMaintainer` replies refresh it at once. Defaults to 30 seconds.", + "pass_interval_ms": { + "description": "Time between the starts of consecutive passes over both heartbeat prefixes. Defaults to one hour.", "type": [ "integer", "null" @@ -1030,44 +930,61 @@ "format": "uint64", "minimum": 0.0 }, - "max_background_cold_reads": { - "description": "Size of each background cold-read window per tablet maintainer: held-image source reads for forks, replica log reads for applies, fork jobs and fork cleanup jobs are each bounded by it separately, so they never take client read slots. Defaults to 4.", + "retention_ms": { + "description": "Defaults to 24 hours; clean shutdown markers remain available during this window.", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint64", "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "Jwt": { + "type": "object", + "properties": { + "audience": { + "type": [ + "string", + "null" + ] }, - "max_cold_reads": { - "description": "Client cold-store reads in flight per tablet maintainer: session opens, lifecycle row lookups and session reads share this window. A cold wake's reads fan out through it, so a narrow window serializes them. Object storage throughput scales almost linearly to about 32 parallel GETs, and a read slot is not always a GET, so 64 keeps a cold wake's reads from waiting on slots; on the load cluster a fully cold wake took about 850 ms at 4, 430 ms at 64 and 390 ms at 512. Defaults to 64.", + "default_duration": { + "description": "Default access-token lifetime, in seconds.", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint64", "minimum": 0.0 }, - "max_cold_reads_per_volume": { - "description": "Client session reads of one volume a tablet maintainer admits while reads of other volumes wait, so one large scan cannot hold every client cold-read slot. Slots no other volume waits for still go to that volume. Unset or 0 admits client reads in arrival order.", + "enabled": { + "description": "Controls verification, issuance, and key maintenance. Defaults to true.", "type": [ - "integer", + "boolean", "null" - ], - "format": "uint32", - "minimum": 0.0 + ] }, - "max_read_sessions": { - "description": "Filesystem read sessions per tablet maintainer. A session lives while its volume is being read and ends after `read_session_idle_ms` without a read, so this bounds how many volumes a tablet serves reads for at once. Opens past it are refused as overloaded. A held session retains about 1.2 KiB of maintainer heap, so the default of 16,384 holds under 20 MiB per tablet. Must be positive.", + "issuance_enabled": { + "description": "Pauses only new token minting. Defaults to true while JWT is enabled.", + "type": [ + "boolean", + "null" + ] + }, + "issuer_generation": { + "description": "Monotonic topology fence. Increment when changing the derived issuer or signing leader.", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "membership_refresh_cooldown_ms": { - "description": "Minimum milliseconds between miss-triggered membership refresh attempts, including failures.", + "key_max_signing_lifetime": { + "description": "Fail-closed maximum signing lifetime, in seconds (fourteen days by default). Normal rotation is still at day seven; this deadline only prevents A from signing forever if rotation stalls.", "type": [ "integer", "null" @@ -1075,8 +992,8 @@ "format": "uint64", "minimum": 0.0 }, - "memtable_flush_throttle_ms": { - "description": "Throttle for memtable flushes that nobody urgently waits on: a pass that comes due waits up to this long, so passes that come due close together share one upload and one L0 SST. Defaults to ten seconds.", + "key_publish_lead": { + "description": "Time to publish a pending public key before activation, in seconds (ten minutes by default). It provides verifier propagation time and does not extend the active key's lifetime.", "type": [ "integer", "null" @@ -1084,8 +1001,8 @@ "format": "uint64", "minimum": 0.0 }, - "read_cursor_session_idle_ms": { - "description": "How long a session opened at the latest position stays registered after its last read, in milliseconds. An HTTP directory cursor resumes such a session between pages, and no client reopens it at its position, so a paging client keeps its cursor for this long between pages. Must be positive. Defaults to 30,000, the session lifetime.", + "key_rotation_interval": { + "description": "Normal active-key age at rotation, in seconds (seven days by default).", "type": [ "integer", "null" @@ -1093,8 +1010,8 @@ "format": "uint64", "minimum": 0.0 }, - "read_session_idle_ms": { - "description": "How long a read session stays registered after its last read, in milliseconds. Each read extends it up to the session's lifetime, and a client reopens an ended session on its next read, so sessions track volumes being read rather than volumes open. Must be positive. Defaults to 2,000.", + "max_duration": { + "description": "Maximum access-token lifetime, in seconds. V1 is capped at one day.", "type": [ "integer", "null" @@ -1102,8 +1019,7 @@ "format": "uint64", "minimum": 0.0 }, - "simulated_fs_read_cost_us": { - "description": "Simulation only: runner time each filesystem read request costs a tablet maintainer, in microseconds, spent on the simulated clock so a maintainer busy with reads queues them as a loaded one does. Unset in deployments, where real processing time passes on its own.", + "unknown_kid_refresh_cooldown": { "type": [ "integer", "null" @@ -1111,8 +1027,7 @@ "format": "uint64", "minimum": 0.0 }, - "stop_poll_ms": { - "description": "Stop-permit retry interval. Defaults to one second.", + "verifier_cache_ttl": { "type": [ "integer", "null" @@ -1120,17 +1035,23 @@ "format": "uint64", "minimum": 0.0 }, - "stop_teardown_ms": { - "description": "Teardown budget after a stop permit or timeout. Defaults to one minute.", + "verifier_max_stale": { "type": [ "integer", "null" ], "format": "uint64", "minimum": 0.0 - }, - "stop_timeout_ms": { - "description": "Maximum coordinated stop wait from the first signal. Defaults to 30 minutes.", + } + }, + "additionalProperties": false + }, + "KvCommandConfig": { + "description": "Optional limits for typed commands and maintainer-owned filesystems.", + "type": "object", + "properties": { + "evicted_idle_warn_ms": { + "description": "Warns on eviction below this idle time; defaults to 15 seconds.", "type": [ "integer", "null" @@ -1138,44 +1059,43 @@ "format": "uint64", "minimum": 0.0 }, - "store_admission_scan_limit": { - "description": "Queued store items one admission pass looks at past work that cannot start yet. Work beyond it waits for the next pass. Must be positive. Defaults to 1024.", + "max_command_bytes": { "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint", "minimum": 0.0 }, - "store_max_flush_staging": { - "description": "Tablet filesystem flushes one tablet maintainer lets stage at once. Staging writes the flush's records into the store. Must be positive. Defaults to 1.", + "max_eviction_closes": { + "description": "Idle KV command volumes one partition's host closes at once to make room past its cap or the worker's budget. Each open refused at a full cap starts one such close, so a burst admits at this many closes per close latency. A closing volume keeps its memory charge until its close finishes. Defaults to 32.", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint", "minimum": 0.0 }, - "store_max_flush_uploads": { - "description": "Tablet filesystem flushes one tablet maintainer keeps in flight at once, staging or uploading; a staging flush counts because it uploads next. Must be at least `store_max_flush_staging`. Defaults to 2.", + "max_inflight_command_bytes": { + "description": "Received bytes of the KV commands one partition's host has admitted and not finished. A command that would exceed it is refused at once as unavailable, which callers retry within their deadline. Must hold at least one command of `max_command_bytes`. Defaults to 64 MiB, so a worker maintaining four partitions holds at most 256 MiB of command payloads.", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint", "minimum": 0.0 }, - "store_max_keyed_in_flight": { - "description": "Filesystem applies and loads one tablet maintainer admits to its store at once. They run concurrently, one task each, and their replica reads stay bounded by the cold byte budget, so the cap sizes concurrency for a burst of volume creates rather than memory. Must be positive. Defaults to 256.", + "max_inflight_commands": { + "description": "Maximum simultaneous handlers per registered command class.", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint", "minimum": 0.0 }, - "store_volume_lock_stripes": { - "description": "Volume lock stripes of each tablet filesystem store. Two volumes on one stripe serialize their store work. Must be positive. Defaults to 1024.", + "max_open_volumes": { + "description": "KV command volumes one partition's host holds open at once, closing ones included. Defaults to the worker-wide cap, so by default only the worker's memory budget limits a partition.", "type": [ "integer", "null" @@ -1183,35 +1103,17 @@ "format": "uint", "minimum": 0.0 }, - "store_volume_locks": { - "description": "Which store work takes volume stripes. `core` (the default) trusts the maintainer core to order applies, loads, session opens, lifecycle lookups and the flush retention publish, so they take only the tablet lock; stripes then guard only checkpoint-session opens against hold releases, checkpoint deletions and sweeps. `stripes` keeps a stripe on every operation, as before.", - "anyOf": [ - { - "$ref": "#/definitions/StoreVolumeLocks" - }, - { - "type": "null" - } - ] - }, - "volume_client": { - "default": { - "close_after_idle_ms": null, - "max_loaded_volumes": null, - "max_requests": null, - "max_volume_key_bytes": null, - "open_timeout_ms": null, - "payload_codec": null, - "sweep_interval_ms": null - }, - "allOf": [ - { - "$ref": "#/definitions/VolumeClientConfig" - } - ] + "max_worker_open_volume_bytes": { + "description": "Memory, in bytes, that the KV command volumes of this worker may hold together across every partition it maintains, closing ones included. Each open volume is charged 80 KiB, its measured fixed cost with allocator headroom: its host slot, volume client and filesystem owner, plus the log replicas and maintainer state its open loads. Caches and command payloads are bounded separately. One worker-wide budget bounds memory however many partitions the worker holds, and a create burst opens one volume per new key, so the default of 5 GiB holds 65,536 volumes (default 5 GiB).", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 }, - "volume_request_capacity": { - "description": "Per-subject lifecycle request capacity, isolated from other UPS traffic. Defaults to 1024.", + "max_worker_open_volumes": { + "description": "A count backstop to `max_worker_open_volume_bytes`; unset by default, so the byte budget alone sets the worker's cap.", "type": [ "integer", "null" @@ -1219,17 +1121,17 @@ "format": "uint", "minimum": 0.0 }, - "volume_request_timeout_ms": { - "description": "Entire lifecycle RPC budget, including route refreshes. Defaults to five seconds.", + "request_capacity": { + "description": "KV commands one worker holds received and unanswered, and that one caller may have outstanding to one worker, isolated from volume lifecycle requests. A full window refuses a command at once as overloaded, and the caller retries it within its deadline. Each partition's host admits at most the sum of its commands' concurrency caps (4,608 with the default caps and the engine's commands), so the default of 32,768 lets those caps, not this window, refuse load first on a worker that maintains up to seven partitions. Defaults to 32,768.", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint", "minimum": 0.0 }, - "write_to_cold_above_bytes": { - "description": "Committed suffix threshold, default 64 MiB and maximum 256 MiB.", + "short_idle_close_ms": { + "description": "Idle close for volumes of short-lived commands, such as one Epoxy key per volume. Closing also begins the volume's unload. Defaults to 2 seconds.", "type": [ "integer", "null" @@ -1237,8 +1139,8 @@ "format": "uint64", "minimum": 0.0 }, - "write_to_cold_after_ms": { - "description": "Cold-write age from the first unflushed entry, plus up to a tenth of it as jitter. Defaults to one minute. Storage workers require the age with its jitter to stay below `stop_timeout_ms`, so a stopping worker never waits on a slower tiering cadence than its own stop budget.", + "volume_idle_close_ms": { + "description": "Defaults to 60 seconds.", "type": [ "integer", "null" @@ -1249,206 +1151,79 @@ }, "additionalProperties": false }, - "Epoxy": { - "description": "Epoxy runs in a single datacenter with fixed membership, so it has no settings yet. The section stays so multi-region settings have a home.", - "type": "object", - "additionalProperties": false - }, - "FileSystemObjectStoreConfig": { - "description": "A local directory used by one engine process at a time. Conditional writes are atomic only among requests of that process.", - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "description": "Created when it does not exist.", - "type": "string" - } - }, - "additionalProperties": false - }, - "FilesystemConfig": { + "LogShardConfig": { + "description": "The log shard owns resolved defaults and validates relationships between these limits.", "type": "object", "properties": { - "max_cache_bytes": { - "description": "Bytes one filesystem's row cache may retain, a fairness ceiling inside `max_process_cache_bytes`.", - "default": 8388608, - "type": "integer", - "format": "uint", + "checkpoint_bytes": { + "type": [ + "integer", + "null" + ], + "format": "uint64", "minimum": 0.0 }, - "max_conflict_window_bytes": { - "default": 4194304, - "type": "integer", - "format": "uint", + "checkpoint_timeout_ms": { + "type": [ + "integer", + "null" + ], + "format": "uint64", "minimum": 0.0 }, - "max_memory_bytes": { - "default": 67108864, - "type": "integer", - "format": "uint", + "disk_read_concurrency": { + "description": "Disk reads executing at once beside the shard's write queue. Each holds one scan buffer of two maximum batches from `max_memory_bytes`. Defaults to 8.", + "type": [ + "integer", + "null" + ], + "format": "uint32", "minimum": 0.0 }, - "max_operation_bytes": { - "default": 8388608, - "type": "integer", + "inbox_capacity": { + "type": [ + "integer", + "null" + ], "format": "uint", "minimum": 0.0 }, - "max_pending_commits": { - "default": 128, - "type": "integer", - "format": "uint", + "manifest_refresh_timeout_ms": { + "type": [ + "integer", + "null" + ], + "format": "uint64", "minimum": 0.0 }, - "max_process_cache_bytes": { - "description": "Bytes all filesystem row caches in one process may retain together.", - "default": 1073741824, - "type": "integer", - "format": "uint", + "max_admission_wait_ms": { + "description": "Longest wait, in milliseconds, of a request other than an append in the shard's inbox. A request that waited longer is refused as overloaded before any work, with a retry hint, so a saturated shard sheds load instead of queueing past the volume client's quorum timeout. Defaults to 1000.", + "type": [ + "integer", + "null" + ], + "format": "uint64", "minimum": 0.0 }, - "max_snapshot_age_ms": { - "default": 30000, - "type": "integer", + "max_append_admission_wait_ms": { + "description": "The same bound for appends, commit announcements, trims and forgets, which carry writes a volume client already admitted or free memory and disk, so opens and other new work are shed first. At least `max_admission_wait_ms` and just under the volume client's 2 s append timeout, past which the client has resent the append anyway. Defaults to 1800.", + "type": [ + "integer", + "null" + ], "format": "uint64", "minimum": 0.0 }, - "max_snapshots": { - "default": 128, - "type": "integer", - "format": "uint", + "max_batch_bytes": { + "type": [ + "integer", + "null" + ], + "format": "uint32", "minimum": 0.0 }, - "max_transaction_age_ms": { - "default": 300000, - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "max_transaction_bytes": { - "description": "Maximum application bytes in one filesystem transaction.", - "default": 134217728, - "type": "integer", - "format": "uint", - "minimum": 0.0 - }, - "max_unapplied_bytes": { - "description": "Most payload bytes one opening may have admitted ahead of the newest position its tablet's maintainer reported applied. A new write past it is refused with a retry hint before it is built, so a writer faster than the apply, as under a slow cold store or compaction, waits at admission instead of growing an unbounded backlog.", - "default": 268435456, - "type": "integer", - "format": "uint", - "minimum": 0.0 - }, - "max_value_bytes": { - "default": 1048576, - "type": "integer", - "format": "uint", - "minimum": 0.0 - }, - "note_ttl_ms": { - "description": "How long a write's overlay notes (\"this page is at this sequence\") outlive the write before the filesystem drops them and keeps their rows only as cache. A later miss on one of those rows reads it from the maintainer once it has applied the write. About ten times the usual apply latency.", - "default": 1000, - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "request_timeout_ms": { - "default": 30000, - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "ForkConfig": { - "description": "Global bounds for source hold cleanup and background cross-region copies.", - "type": "object", - "properties": { - "check_grace_ms": { - "description": "Minimum age before an unfinished fork's destination is checked.", - "default": 60000, - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "materialize_batch_chunks": { - "description": "Further bounded by the maintainer's row and byte budgets.", - "default": 1024, - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "max_concurrent_materializations": { - "default": 2, - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "GcsObjectStoreConfig": { - "description": "Google Cloud Storage; defaults to the adapter's application default credentials.", - "type": "object", - "required": [ - "bucket" - ], - "properties": { - "bucket": { - "type": "string" - }, - "prefix": { - "default": null, - "type": [ - "string", - "null" - ] - }, - "service_account_key": { - "description": "Optional JSON service account credential override.", - "default": null, - "anyOf": [ - { - "$ref": "#/definitions/Secret" - }, - { - "type": "null" - } - ] - } - }, - "additionalProperties": false - }, - "Guard": { - "type": "object", - "properties": { - "disable_gateway_auth": { - "description": "TODO: Remove eventually and reenable gateway auth permanently. See RVTEE-672.", - "default": false, - "type": "boolean" - }, - "host": { - "description": "Host for HTTP traffic", - "type": [ - "string", - "null" - ], - "format": "ip" - }, - "port": { - "description": "Port for HTTP traffic", - "type": [ - "integer", - "null" - ], - "format": "uint16", - "minimum": 0.0 - }, - "route_auth_check_timeout_ms": { - "description": "Timeout for guard-owned route authorization checks in milliseconds.", + "max_disk_bytes": { + "description": "Disk bytes the shard's log may hold. When unset, a storage worker sizes it from the free space of its filesystem at startup, shared with the cold-store disk cache.", "type": [ "integer", "null" @@ -1456,17 +1231,17 @@ "format": "uint64", "minimum": 0.0 }, - "route_compute_timeout_ms": { - "description": "Timeout for resolving compute routes in milliseconds.", + "max_disk_reads": { + "description": "Most reads waiting on the shard's disk at once; a read that needs disk beyond it is rejected as overloaded and retried by the caller. Defaults to 256.", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint32", "minimum": 0.0 }, - "route_pegboard_auth_check_timeout_ms": { - "description": "Timeout for pegboard actor route authorization checks in milliseconds.", + "max_loaded_volume_bytes": { + "description": "Memory, in bytes, that one log shard's loaded replicas may hold, charged at 1.5 KiB per replica, the measured heap of a quiet loaded replica with headroom. A load past it is refused as `too_many_loaded_volumes`, a typed refusal its open retries. The default of 1.5 GiB holds 1,048,576 replicas (default 1.5 GiB).", "type": [ "integer", "null" @@ -1474,45 +1249,16 @@ "format": "uint64", "minimum": 0.0 }, - "tcp_nodelay": { - "description": "Enables TCP_NODELAY on accepted Guard sockets. Defaults to true.\n\nGuard carries actor runners' Envoy WebSockets and client WebSocket and HTTP traffic, where most writes are small frames. With Nagle's algorithm on, a small frame waits for the peer to acknowledge the previous one, and a peer that delays its ACK holds it for about 40 ms. That delay landed on every actor's first response.", - "type": [ - "boolean", - "null" - ] - } - }, - "additionalProperties": false - }, - "HardwareMetrics": { - "description": "Configuration for host hardware metrics.", - "type": "object", - "properties": { - "disk_probe": { - "description": "Times sequential writes and fsyncs on each data directory once at startup, in the background. Defaults to true.", - "type": [ - "boolean", - "null" - ] - }, - "disk_probe_bytes": { - "description": "Bytes the probe writes sequentially to each data directory. The fsync phase writes a further 400 KiB. Defaults to 64 MiB; at most 1 GiB.", + "max_loaded_volumes": { + "description": "A count backstop to `max_loaded_volume_bytes`; unset by default, so the byte budget alone sets the shard's replica cap.", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint32", "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "HeartbeatGcConfig": { - "description": "Optional overrides for topology's bounded heartbeat cleanup service, which runs under the storage owner's singleton election. Topology defines the resolved defaults.", - "type": "object", - "properties": { - "batch_interval_ms": { - "description": "Pause between the batches of one pass. Defaults to 10 seconds.", + }, + "max_memory_bytes": { "type": [ "integer", "null" @@ -1520,17 +1266,16 @@ "format": "uint64", "minimum": 0.0 }, - "batch_size": { - "description": "LIST entries examined per batch, 1 to 1000. Defaults to 128.", + "max_memory_requests": { "type": [ "integer", "null" ], - "format": "uint", + "format": "uint32", "minimum": 0.0 }, - "batch_timeout_ms": { - "description": "Time budget of one batch. Defaults to 2 seconds.", + "max_retained_payload_bytes": { + "description": "Encoded bytes of synced log entry payloads the shard keeps in memory for reads; defaults to a sixteenth of `max_memory_bytes`. Older payloads are read from disk.", "type": [ "integer", "null" @@ -1538,17 +1283,8 @@ "format": "uint64", "minimum": 0.0 }, - "delete_concurrency": { - "description": "Conditional deletes in flight per batch, 1 to `batch_size`. Defaults to 4.", - "type": [ - "integer", - "null" - ], - "format": "uint", - "minimum": 0.0 - }, - "pass_interval_ms": { - "description": "Time between the starts of consecutive passes over both heartbeat prefixes. Defaults to one hour.", + "max_retained_payload_bytes_per_volume": { + "description": "Synced payload bytes one volume replica keeps after each disk write; defaults to 32 KiB.", "type": [ "integer", "null" @@ -1556,29 +1292,16 @@ "format": "uint64", "minimum": 0.0 }, - "retention_ms": { - "description": "Defaults to 24 hours; clean shutdown markers remain available during this window.", + "max_write_bytes": { "type": [ "integer", "null" ], "format": "uint64", "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "Jwt": { - "type": "object", - "properties": { - "audience": { - "type": [ - "string", - "null" - ] }, - "default_duration": { - "description": "Default access-token lifetime, in seconds.", + "overload_retry_after_ms": { + "description": "Retry hint, in milliseconds, on a request refused because the inbox or a request budget is full. Defaults to 100.", "type": [ "integer", "null" @@ -1586,31 +1309,15 @@ "format": "uint64", "minimum": 0.0 }, - "enabled": { - "description": "Controls verification, issuance, and key maintenance. Defaults to true.", - "type": [ - "boolean", - "null" - ] - }, - "issuance_enabled": { - "description": "Pauses only new token minting. Defaults to true while JWT is enabled.", + "preallocate_segments": { + "description": "Writes log segments into files zero-filled to `segment_bytes` ahead of use, so each commit overwrites allocated blocks and syncs only its data instead of journaling a file size change. On the load cluster's disks this halves the sync and commit latency. The unused allocation of the active segment and one spare segment count toward `max_disk_bytes`. Each write also records, in a header slot synced with it, how far earlier syncs reached, so a disk that returns synced pages as zeros is reported as corruption rather than read as free space. Needs `segment_bytes` above 8 KiB. Defaults to true.", "type": [ "boolean", "null" ] }, - "issuer_generation": { - "description": "Monotonic topology fence. Increment when changing the derived issuer or signing leader.", - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0.0 - }, - "key_max_signing_lifetime": { - "description": "Fail-closed maximum signing lifetime, in seconds (fourteen days by default). Normal rotation is still at day seven; this deadline only prevents A from signing forever if rotation stalls.", + "recovery_timeout_ms": { + "description": "How long log shard recovery may go without finishing another file before the shard fails (default 120 s). It does not bound the whole scan, which grows with the log.", "type": [ "integer", "null" @@ -1618,8 +1325,8 @@ "format": "uint64", "minimum": 0.0 }, - "key_publish_lead": { - "description": "Time to publish a pending public key before activation, in seconds (ten minutes by default). It provides verifier propagation time and does not extend the active key's lifetime.", + "release_idle_payloads_after_ms": { + "description": "How long a volume replica appends nothing before its synced payloads leave memory; defaults to 5000.", "type": [ "integer", "null" @@ -1627,8 +1334,7 @@ "format": "uint64", "minimum": 0.0 }, - "key_rotation_interval": { - "description": "Normal active-key age at rotation, in seconds (seven days by default).", + "remove_segments_timeout_ms": { "type": [ "integer", "null" @@ -1636,8 +1342,7 @@ "format": "uint64", "minimum": 0.0 }, - "max_duration": { - "description": "Maximum access-token lifetime, in seconds. V1 is capped at one day.", + "segment_bytes": { "type": [ "integer", "null" @@ -1645,92 +1350,146 @@ "format": "uint64", "minimum": 0.0 }, - "unknown_kid_refresh_cooldown": { + "write_to_cold_at_disk_percent": { + "description": "Early cold-write watermark, 1..99 percent of the disk cap; defaults to 75.", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint8", "minimum": 0.0 }, - "verifier_cache_ttl": { + "write_to_disk_timeout_ms": { "type": [ "integer", "null" ], "format": "uint64", "minimum": 0.0 - }, - "verifier_max_stale": { + } + }, + "additionalProperties": false + }, + "Logs": { + "type": "object", + "properties": { + "redirect_logs_dir": { + "default": null, "type": [ - "integer", + "string", "null" - ], - "format": "uint64", - "minimum": 0.0 + ] } }, "additionalProperties": false }, - "KvCommandConfig": { - "description": "Optional limits for typed commands and maintainer-owned filesystems.", + "Metrics": { + "description": "Configuration for the metrics service.", "type": "object", "properties": { - "evicted_idle_warn_ms": { - "description": "Warns on eviction below this idle time; defaults to 15 seconds.", + "hardware": { + "description": "Host hardware metrics, including a short disk probe of each data directory at startup.", + "default": { + "disk_probe": null, + "disk_probe_bytes": null + }, + "allOf": [ + { + "$ref": "#/definitions/HardwareMetrics" + } + ] + }, + "host": { "type": [ - "integer", + "string", "null" ], - "format": "uint64", - "minimum": 0.0 + "format": "ip" }, - "max_command_bytes": { + "port": { "type": [ "integer", "null" ], - "format": "uint", + "format": "uint16", "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "MigrateFromV2": { + "description": "Settings for moving one V2 namespace's actors into this cluster.\n\nThe section is read through `config.dynamic()`, and a dynamic config update replaces it as a whole. `migrate_seed` is the exception: it is fixed at startup, because a new seed reshuffles which actors fall under `migrate_ratio`, so raising the ratio would no longer only add actors.", + "type": "object", + "required": [ + "endpoint", + "namespace" + ], + "properties": { + "api_urls": { + "description": "V2's public API per datacenter label, which the migrator lists and moves actors through.", + "default": {}, + "type": "object", + "additionalProperties": { + "type": "string" + } }, - "max_eviction_closes": { - "description": "Idle KV command volumes one tablet's host closes at once to make room past its cap or the worker's budget. Each open refused at a full cap starts one such close, so a burst admits at this many closes per close latency. A closing volume keeps its memory charge until its close finishes. Defaults to 32.", + "confirm_delay_ms": { "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "max_inflight_command_bytes": { - "description": "Received bytes of the KV commands one tablet's host has admitted and not finished. A command that would exceed it is refused at once as unavailable, which callers retry within their deadline. Must hold at least one command of `max_command_bytes`. Defaults to 64 MiB, so a worker maintaining four tablets holds at most 256 MiB of command payloads.", + "create_ratio": { + "description": "Share of new creates that land in this cluster. Keyless creates draw against it; keyed creates move here only at 1.0.", + "default": 0.0, + "type": "number", + "format": "double" + }, + "endpoint": { + "description": "V2's public gateway, where requests for actors this cluster does not hold are proxied.", + "type": "string" + }, + "max_actors_per_sec": { "type": [ "integer", "null" ], - "format": "uint", + "format": "uint32", "minimum": 0.0 }, - "max_inflight_commands": { - "description": "Maximum simultaneous handlers per registered command class.", + "max_copy_bytes": { + "description": "Largest actor the migrator copies, by V2's reported SQLite size plus its KV estimate. Larger actors are skipped as `too_large` on every pass, so they never hold a slot; raise it once the rest of the namespace has moved to migrate them. Defaults to 10 GiB.", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "max_open_volumes": { - "description": "KV command volumes one tablet's host holds open at once, closing ones included. Defaults to the worker-wide cap, so by default only the worker's memory budget limits a tablet.", + "max_in_flight": { "type": [ "integer", "null" ], - "format": "uint", + "format": "uint32", "minimum": 0.0 }, - "max_worker_open_volume_bytes": { - "description": "Memory, in bytes, that the KV command volumes of this worker may hold together across every tablet it maintains, closing ones included. Each open volume is charged 80 KiB, its measured fixed cost with allocator headroom: its host slot, volume client and filesystem owner, plus the log replicas and maintainer state its open loads. Caches and command payloads are bounded separately. One worker-wide budget bounds memory however many tablets the worker holds, and a create burst opens one volume per new key, so the default of 5 GiB holds 65,536 volumes (default 5 GiB).", + "migrate_ratio": { + "description": "Share of existing V2 actors the migrator moves, picked by a stable hash of the actor id.", + "default": 0.0, + "type": "number", + "format": "double" + }, + "migrate_seed": { + "description": "Seed of the hash behind `migrate_ratio`.", + "default": 0, + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "min_sleep_ms": { "type": [ "integer", "null" @@ -1738,35 +1497,35 @@ "format": "uint64", "minimum": 0.0 }, - "max_worker_open_volumes": { - "description": "A count backstop to `max_worker_open_volume_bytes`; unset by default, so the byte budget alone sets the worker's cap.", + "namespace": { + "description": "The V2 namespace being migrated.", + "type": "string" + }, + "pass_interval_ms": { "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "request_capacity": { - "description": "KV commands one worker holds received and unanswered, and that one caller may have outstanding to one worker, isolated from volume lifecycle requests. A full window refuses a command at once as overloaded, and the caller retries it within its deadline. Each tablet's host admits at most the sum of its commands' concurrency caps (4,608 with the default caps and the engine's commands), so the default of 32,768 lets those caps, not this window, refuse load first on a worker that maintains up to seven tablets. Defaults to 32,768.", + "target_namespace": { + "description": "The namespace here that the actors land in. Defaults to the V2 namespace's name.", + "default": null, "type": [ - "integer", + "string", "null" - ], - "format": "uint", - "minimum": 0.0 + ] }, - "short_idle_close_ms": { - "description": "Idle close for volumes of short-lived commands, such as one Epoxy key per volume. Closing also begins the volume's unload. Defaults to 2 seconds.", + "token": { + "description": "The namespace-wide V2 token for V2's migration API and the public API calls routing makes. Never logged.", + "default": null, "type": [ - "integer", + "string", "null" - ], - "format": "uint64", - "minimum": 0.0 + ] }, - "volume_idle_close_ms": { - "description": "Defaults to 60 seconds.", + "wake_horizon_ms": { "type": [ "integer", "null" @@ -1777,11 +1536,20 @@ }, "additionalProperties": false }, - "LogShardConfig": { - "description": "The log shard owns resolved defaults and validates relationships between these limits.", + "ObjectStorageConfig": { "type": "object", "properties": { - "checkpoint_bytes": { + "primary": { + "default": "in_memory", + "allOf": [ + { + "$ref": "#/definitions/ObjectStoreBackend" + } + ] + }, + "read_first_attempt_ms": { + "description": "Milliseconds the first attempt of a small GET or HEAD may wait for response headers before the client cuts it off and retries it with its normal timeouts. A request on a stalled connection otherwise waits the full 30 s client timeout. Default 250, set from the load cluster's Azure account, where about 0.02% of small requests took longer; 0 disables it. Response bodies are never cut off.", + "default": null, "type": [ "integer", "null" @@ -1789,7 +1557,9 @@ "format": "uint64", "minimum": 0.0 }, - "checkpoint_timeout_ms": { + "write_first_attempt_bytes_per_second": { + "description": "The upload rate a conditional PUT's first attempt may fall to before it is cut off, which extends `write_first_attempt_ms` by the body's size. Default 8 MiB/s.", + "default": null, "type": [ "integer", "null" @@ -1797,288 +1567,367 @@ "format": "uint64", "minimum": 0.0 }, - "disk_read_concurrency": { - "description": "Disk reads executing at once beside the shard's write queue. Each holds one scan buffer of two maximum batches from `max_memory_bytes`. Defaults to 8.", + "write_first_attempt_ms": { + "description": "Milliseconds the first attempt of a small conditional PUT (a lease, heartbeat or manifest) may wait for response headers, before the upload time its body needs at `write_first_attempt_bytes_per_second`. Unset by default, which disables it. Healthy conditional PUT latency is calibrated only on Azure; a healthy GCS PUT can take over 250 ms. GCS also allows about one write per second to one object, so a retry shortly after a cut-off on the same lease or heartbeat object risks a 429, an unknown outcome and an extra readback. Set it only from measured conditional PUT latency of the backend.", + "default": null, "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint64", "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "ObjectStoreBackend": { + "oneOf": [ + { + "type": "string", + "enum": [ + "in_memory" + ] }, - "inbox_capacity": { + { + "description": "A local directory, for a single engine process that keeps its data across restarts.", + "type": "object", + "required": [ + "file_system" + ], + "properties": { + "file_system": { + "$ref": "#/definitions/FileSystemObjectStoreConfig" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "s3" + ], + "properties": { + "s3": { + "$ref": "#/definitions/S3ObjectStoreConfig" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "azure" + ], + "properties": { + "azure": { + "$ref": "#/definitions/AzureObjectStoreConfig" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "gcs" + ], + "properties": { + "gcs": { + "$ref": "#/definitions/GcsObjectStoreConfig" + } + }, + "additionalProperties": false + } + ] + }, + "Outbound": { + "description": "Policy for outbound HTTP requests to user-configured destinations, such as serverless node URLs.\n\nThese requests originate from inside the trusted engine network, so without restrictions a caller who can configure a node can reach internal-only services. The defaults deny every non-globally-routable destination except loopback.", + "type": "object", + "properties": { + "allow_cidrs": { + "description": "Additional CIDRs that are always permitted, evaluated after `deny_cidrs`.\n\nUse this to reach a specific internal service without opening up the whole private range.", "type": [ - "integer", + "array", "null" ], - "format": "uint", - "minimum": 0.0 + "items": { + "type": "string" + } }, - "manifest_refresh_timeout_ms": { + "allow_hosts": { + "description": "Hostnames that are always permitted, whatever they resolve to.\n\nMatched exactly and case-insensitively, with no wildcards. Use this for a first-party service whose address is not known ahead of time, such as a Kubernetes service name. Anything served at a listed host becomes reachable by every node config, so list individual hosts rather than a shared entry point.", "type": [ - "integer", + "array", "null" ], - "format": "uint64", - "minimum": 0.0 + "items": { + "type": "string" + } }, - "max_admission_wait_ms": { - "description": "Longest wait, in milliseconds, of a request other than an append in the shard's inbox. A request that waited longer is refused as overloaded before any work, with a retry hint, so a saturated shard sheds load instead of queueing past the volume client's quorum timeout. Defaults to 1000.", + "allow_insecure_scheme": { + "description": "Allow plaintext `http://` destinations. When disabled only `https://` is permitted.", "type": [ - "integer", + "boolean", "null" - ], - "format": "uint64", - "minimum": 0.0 + ] }, - "max_append_admission_wait_ms": { - "description": "The same bound for appends, commit announcements, trims and forgets, which carry writes a volume client already admitted or free memory and disk, so opens and other new work are shed first. At least `max_admission_wait_ms` and just under the volume client's 2 s append timeout, past which the client has resent the append anyway. Defaults to 1800.", + "allow_loopback": { + "description": "Allow destinations that resolve to loopback addresses (127.0.0.0/8, ::1).\n\nEnabled by default so local development against `http://localhost:...` works without configuration.", "type": [ - "integer", + "boolean", "null" - ], - "format": "uint64", - "minimum": 0.0 + ] }, - "max_batch_bytes": { + "allow_private_networks": { + "description": "Allow destinations that resolve to private, link-local, shared (CGNAT), or otherwise non-globally-routable addresses.\n\nSelf-hosted deployments that point nodes at addresses on their own network, such as a Docker Compose service name, need this enabled.", "type": [ - "integer", + "boolean", + "null" + ] + }, + "deny_cidrs": { + "description": "Additional CIDRs that are always denied. Takes precedence over every allow rule.", + "type": [ + "array", "null" ], - "format": "uint32", - "minimum": 0.0 + "items": { + "type": "string" + } }, - "max_disk_bytes": { - "description": "Disk bytes the shard's log may hold. When unset, a storage worker sizes it from the free space of its filesystem at startup, shared with the cold-store disk cache.", + "max_redirects": { + "description": "Maximum number of redirects to follow. Every hop is re-checked against this policy.", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "PartitionBalancingConfig": { + "description": "Static partition placement policy; membership and lease timings remain topology-owned.", + "type": "object", + "properties": { + "destination_stability_ms": { + "description": "How long a new worker must be listed in discovery, and pass one disk probe, before the coordinator places partitions on it. Must exceed the topology worker lease plus one renewal and the takeover grace, about 35 s, so a worker that crashes soon after it first appears has left discovery before it qualifies. Startup refuses a shorter value.", + "default": 60000, + "type": "integer", + "format": "uint64", "minimum": 0.0 }, - "max_disk_reads": { - "description": "Most reads waiting on the shard's disk at once; a read that needs disk beyond it is rejected as overloaded and retried by the caller. Defaults to 256.", - "type": [ - "integer", - "null" - ], + "enabled": { + "description": "Whether the partition coordinator places, splits and replaces partitions on its own. When disabled, the layout changes only through operator commands: a new cluster gets no first partition until an operator creates one, and a missing worker is never replaced.", + "default": true, + "type": "boolean" + }, + "max_disk_probes": { + "description": "Maximum concurrent disk admission requests made by the partition coordinator.", + "default": 4, + "type": "integer", "format": "uint32", "minimum": 0.0 }, - "max_loaded_volume_bytes": { - "description": "Memory, in bytes, that one log shard's loaded replicas may hold, charged at 1.5 KiB per replica, the measured heap of a quiet loaded replica with headroom. A load past it is refused as `too_many_loaded_volumes`, a typed refusal its open retries. The default of 1.5 GiB holds 1,048,576 replicas (default 1.5 GiB).", + "missing_worker_ms": { + "description": "How long an assigned worker must be missing from discovery before its replicas are replaced. Counted from when discovery drops it, which is itself one lease after its last renewal.", + "default": 120000, + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "partitions_per_core": { + "default": 2, + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "PeerTransport": { + "description": "Connections and flow-control windows per peer. Omitted values use the defaults.", + "type": "object", + "properties": { + "channel_large_request_bytes": { + "description": "Requests with a larger payload use a peer's large-request channels, so they never queue ahead of small requests on one stream (default 64 KiB).", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint", "minimum": 0.0 }, - "max_loaded_volumes": { - "description": "A count backstop to `max_loaded_volume_bytes`; unset by default, so the byte budget alone sets the shard's replica cap.", + "channel_max_write_bytes": { + "description": "Most bytes a peer channel writes at once from its queue (default 256 KiB).", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint", "minimum": 0.0 }, - "max_memory_bytes": { + "channel_queue_bytes": { + "description": "Bytes of requests a peer channel queues for writing; a request that would exceed it is refused, though an empty queue always takes one (default 64 MiB).", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint", "minimum": 0.0 }, - "max_memory_requests": { + "channel_queue_frames": { + "description": "Frames a peer channel queues for writing; a full queue refuses the request (default 8192).", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint", "minimum": 0.0 }, - "max_retained_payload_bytes": { - "description": "Encoded bytes of synced log entry payloads the shard keeps in memory for reads; defaults to a sixteenth of `max_memory_bytes`. Older payloads are read from disk.", + "channel_reply_queue_bytes": { + "description": "Bytes of replies one served peer channel queues for writing. A channel at its cap refuses new requests as overloaded until its caller reads or the queued replies expire (default 64 MiB).", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint", "minimum": 0.0 }, - "max_retained_payload_bytes_per_volume": { - "description": "Synced payload bytes one volume replica keeps after each disk write; defaults to 32 KiB.", + "incoming_channel_capacity": { + "description": "Peer channels this worker may serve across all remote workers (default 4096).", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint", "minimum": 0.0 }, - "max_write_bytes": { + "outgoing_channel_capacity": { + "description": "Peer channels this worker may open across all remote workers (default 4096).", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint", "minimum": 0.0 }, - "overload_retry_after_ms": { - "description": "Retry hint, in milliseconds, on a request refused because the inbox or a request budget is full. Defaults to 100.", + "reply_queue_bytes": { + "description": "Bytes of replies queued across every served peer channel of this worker. At the cap every channel refuses new requests as overloaded (default 1 GiB).", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint", "minimum": 0.0 }, - "preallocate_segments": { - "description": "Writes log segments into files zero-filled to `segment_bytes` ahead of use, so each commit overwrites allocated blocks and syncs only its data instead of journaling a file size change. On the load cluster's disks this halves the sync and commit latency. The unused allocation of the active segment and one spare segment count toward `max_disk_bytes`. Each write also records, in a header slot synced with it, how far earlier syncs reached, so a disk that returns synced pages as zeros is reported as corruption rather than read as free space. Needs `segment_bytes` above 8 KiB. Defaults to true.", + "request_connection_window_bytes": { + "description": "HTTP/2 connection window of a request connection (default 16 MiB).", "type": [ - "boolean", + "integer", "null" - ] + ], + "format": "uint32", + "minimum": 0.0 }, - "recovery_timeout_ms": { - "description": "How long log shard recovery may go without finishing another file before the shard fails (default 120 s). It does not bound the whole scan, which grows with the log.", + "request_connections": { + "description": "Connections per peer for unary requests, each carrying one peer channel (default 4).", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint", "minimum": 0.0 }, - "release_idle_payloads_after_ms": { - "description": "How long a volume replica appends nothing before its synced payloads leave memory; defaults to 5000.", + "request_stream_window_bytes": { + "description": "HTTP/2 stream window this worker grants a peer channel's replies (default 4 MiB). A worker's server grants each incoming stream a fixed 4 MiB window.", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint32", "minimum": 0.0 }, - "remove_segments_timeout_ms": { + "server_connection_capacity": { + "description": "TCP connections the internal HTTP listener may serve at once (default 8192).", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint", "minimum": 0.0 }, - "segment_bytes": { + "stream_connection_window_bytes": { + "description": "HTTP/2 connection window of a stream connection (default 32 MiB).", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint32", "minimum": 0.0 }, - "write_to_cold_at_disk_percent": { - "description": "Early cold-write watermark, 1..99 percent of the disk cap; defaults to 75.", + "stream_connections": { + "description": "Connections per peer for long-lived streams such as tunnels (default 2).", "type": [ "integer", "null" ], - "format": "uint8", + "format": "uint", "minimum": 0.0 }, - "write_to_disk_timeout_ms": { + "stream_stream_window_bytes": { + "description": "HTTP/2 stream window of a long-lived stream (default 1 MiB).", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint32", "minimum": 0.0 } }, "additionalProperties": false }, - "Logs": { + "Pegboard": { "type": "object", "properties": { - "redirect_logs_dir": { - "default": null, + "actor_index_buckets_per_name": { + "description": "Hashed index bucket volumes for each namespace and actor name (default 8, 1..=256).\n\nThis is part of the index address format. Changing it on a running cluster strands existing rows in buckets that listing and destroy no longer target, so treat it as fixed per cluster.", "type": [ - "string", + "integer", "null" - ] - } - }, - "additionalProperties": false - }, - "Metadata": { - "type": "object", - "required": [ - "project" - ], - "properties": { - "project": { - "type": "string" - } - }, - "additionalProperties": false - }, - "Metrics": { - "description": "Configuration for the metrics service.", - "type": "object", - "properties": { - "hardware": { - "description": "Host hardware metrics, including a short disk probe of each data directory at startup.", - "default": { - "disk_probe": null, - "disk_probe_bytes": null - }, - "allOf": [ - { - "$ref": "#/definitions/HardwareMetrics" - } - ] + ], + "format": "uint64", + "minimum": 0.0 }, - "host": { + "actor_index_list_concurrency": { + "description": "Maximum actor index bucket pages one listing reads at once (default 32).", "type": [ - "string", + "integer", "null" ], - "format": "ip" + "format": "uint", + "minimum": 0.0 }, - "port": { + "actor_index_reaper_max_concurrency": { + "description": "Lazy orphan deletes an actor listing runs at once (default 16).", "type": [ "integer", "null" ], - "format": "uint16", + "format": "uint", "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "ObjectStorageConfig": { - "type": "object", - "properties": { - "primary": { - "default": "in_memory", - "allOf": [ - { - "$ref": "#/definitions/ObjectStoreBackend" - } - ] }, - "read_first_attempt_ms": { - "description": "Milliseconds the first attempt of a small GET or HEAD may wait for response headers before the client cuts it off and retries it with its normal timeouts. A request on a stalled connection otherwise waits the full 30 s client timeout. Default 250, set from the load cluster's Azure account, where about 0.02% of small requests took longer; 0 disables it. Response bodies are never cut off.", - "default": null, + "actor_index_reaper_max_pending": { + "description": "Rows an actor listing's lazy orphan deletes may queue at once (default 1024).", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint", "minimum": 0.0 }, - "write_first_attempt_bytes_per_second": { - "description": "The upload rate a conditional PUT's first attempt may fall to before it is cut off, which extends `write_first_attempt_ms` by the body's size. Default 8 MiB/s.", - "default": null, + "actor_key_cache_capacity": { + "description": "Actor key reservations and key epochs cached in one process, each (default 100000). Reservations never change, so a cached one is kept until evicted.", "type": [ "integer", "null" @@ -2086,178 +1935,103 @@ "format": "uint64", "minimum": 0.0 }, - "write_first_attempt_ms": { - "description": "Milliseconds the first attempt of a small conditional PUT (a lease, heartbeat or manifest) may wait for response headers, before the upload time its body needs at `write_first_attempt_bytes_per_second`. Unset by default, which disables it. Healthy conditional PUT latency is calibrated only on Azure; a healthy GCS PUT can take over 250 ms. GCS also allows about one write per second to one object, so a retry shortly after a cut-off on the same lease or heartbeat object risks a 429, an unknown outcome and an extra readback. Set it only from measured conditional PUT latency of the backend.", - "default": null, + "actor_start_notice_timeout_ms": { + "description": "Timeout of one start notice to a waiting gateway worker. Unit is in milliseconds (default 2000, 100..=30000).", "type": [ "integer", "null" ], "format": "uint64", "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "ObjectStoreBackend": { - "oneOf": [ - { - "type": "string", - "enum": [ - "in_memory" - ] }, - { - "description": "A local directory, for a single engine process that keeps its data across restarts.", - "type": "object", - "required": [ - "file_system" + "actor_start_threshold": { + "description": "How long the engine waits after sending an actor's start for the node to report it running. Past it the start is given up: the node is told to stop that epoch, and the actor starts again once the node reports it stopped or is proven gone.\n\nUnit is in milliseconds (default 30000).", + "type": [ + "integer", + "null" ], - "properties": { - "file_system": { - "$ref": "#/definitions/FileSystemObjectStoreConfig" - } - }, - "additionalProperties": false + "format": "uint64", + "minimum": 0.0 }, - { - "type": "object", - "required": [ - "s3" + "actor_start_waiters_capacity": { + "description": "Gateway workers one actor keeps waiting for its start (default 64, 1..=1024). A request that finds the list full waits on its fallback poll alone.", + "type": [ + "integer", + "null" ], - "properties": { - "s3": { - "$ref": "#/definitions/S3ObjectStoreConfig" - } - }, - "additionalProperties": false + "format": "uint32", + "minimum": 0.0 }, - { - "type": "object", - "required": [ - "azure" - ], - "properties": { - "azure": { - "$ref": "#/definitions/AzureObjectStoreConfig" - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "gcs" - ], - "properties": { - "gcs": { - "$ref": "#/definitions/GcsObjectStoreConfig" - } - }, - "additionalProperties": false - } - ] - }, - "Outbound": { - "description": "Policy for outbound HTTP requests to user-configured destinations, such as serverless runner URLs.\n\nThese requests originate from inside the trusted engine network, so without restrictions a caller who can configure a runner can reach internal-only services. The defaults deny every non-globally-routable destination except loopback.", - "type": "object", - "properties": { - "allow_cidrs": { - "description": "Additional CIDRs that are always permitted, evaluated after `deny_cidrs`.\n\nUse this to reach a specific internal service without opening up the whole private range.", - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } - }, - "allow_hosts": { - "description": "Hostnames that are always permitted, whatever they resolve to.\n\nMatched exactly and case-insensitively, with no wildcards. Use this for a first-party service whose address is not known ahead of time, such as a Kubernetes service name. Anything served at a listed host becomes reachable by every runner config, so list individual hosts rather than a shared entry point.", + "actor_stop_threshold": { + "description": "How long a node may take to stop its actors once asked, advertised to the node on connect. A node shutting down drains its actors within this budget, and RivetKit uses it as the default shutdown grace period.\n\nUnit is in milliseconds (default 1800000, 30 minutes).", "type": [ - "array", + "integer", "null" ], - "items": { - "type": "string" - } - }, - "allow_insecure_scheme": { - "description": "Allow plaintext `http://` destinations. When disabled only `https://` is permitted.", - "type": [ - "boolean", - "null" - ] - }, - "allow_loopback": { - "description": "Allow destinations that resolve to loopback addresses (127.0.0.0/8, ::1).\n\nEnabled by default so local development against `http://localhost:...` works without configuration.", - "type": [ - "boolean", - "null" - ] + "format": "uint64", + "minimum": 0.0 }, - "allow_private_networks": { - "description": "Allow destinations that resolve to private, link-local, shared (CGNAT), or otherwise non-globally-routable addresses.\n\nSelf-hosted deployments that point runners at addresses on their own network, such as a Docker Compose service name, need this enabled.", - "type": [ - "boolean", - "null" + "command_concurrency": { + "description": "Per-class handler concurrency for the storage commands pegboard registers on storage workers.", + "default": { + "actor": null, + "actor_event": null, + "actor_read": null, + "index": null + }, + "allOf": [ + { + "$ref": "#/definitions/CommandConcurrency" + } ] }, - "deny_cidrs": { - "description": "Additional CIDRs that are always denied. Takes precedence over every allow rule.", + "gateway_port": { + "description": "Port for the new partition-backed gateway and node Hyper listener (default 6422).", "type": [ - "array", + "integer", "null" ], - "items": { - "type": "string" - } + "format": "uint16", + "minimum": 0.0 }, - "max_redirects": { - "description": "Maximum number of redirects to follow. Every hop is re-checked against this policy.", + "gateway_retry_budget_max_tokens": { + "description": "Retries one gateway process can bank for a burst of refusals; the budget starts full (default 100, 0..=100000).", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint32", "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "PeerTransport": { - "description": "Connections and flow-control windows per peer. Omitted values use the defaults.", - "type": "object", - "properties": { - "channel_large_request_bytes": { - "description": "Requests with a larger payload use a peer's large-request channels, so they never queue ahead of small requests on one stream (default 64 KiB).", + }, + "gateway_retry_budget_percent": { + "description": "Retries of refused requests one gateway process allows, as a percentage of the requests it receives (default 10, 0..=100). A refused request past this budget fails with `guard.service_unavailable` and its retry hint, so the client owns the next attempt.", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint32", "minimum": 0.0 }, - "channel_max_write_bytes": { - "description": "Most bytes a peer channel writes at once from its queue (default 256 KiB).", + "gateway_start_poll_after_ms": { + "description": "Time after a gateway request starts waiting for an actor's start notice before its first fallback read. Unit is in milliseconds (default 2000, 100..=30000).", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "channel_queue_bytes": { - "description": "Bytes of requests a peer channel queues for writing; a request that would exceed it is refused, though an empty queue always takes one (default 64 MiB).", + "gateway_start_poll_interval_ms": { + "description": "Time between later fallback reads while a gateway request waits for an actor's start. Unit is in milliseconds (default 2000, 100..=30000).", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "channel_queue_frames": { - "description": "Frames a peer channel queues for writing; a full queue refuses the request (default 8192).", + "gateway_start_waits_capacity": { + "description": "Actors one gateway process waits on at once for a start notice (default 65536, 1..=1048576). When full, a new request waits on its fallback poll alone.", "type": [ "integer", "null" @@ -2265,17 +2039,17 @@ "format": "uint", "minimum": 0.0 }, - "channel_reply_queue_bytes": { - "description": "Bytes of replies one served peer channel queues for writing. A channel at its cap refuses new requests as overloaded until its caller reads or the queued replies expire (default 64 MiB).", + "gateway_websocket_open_timeout_ms": { + "description": "Time an actor WebSocket upgrade may wait for its actor, as while storage recovers after an engine restart. Past it the gateway accepts the upgrade and closes it with `guard.service_unavailable` and a retry hint, so a client without a connect timeout retries instead of waiting forever. Unit is in milliseconds (default 15000, 1000..=45000).", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "reply_queue_bytes": { - "description": "Bytes of replies queued across every served peer channel of this worker. At the cap every channel refuses new requests as overloaded (default 1 GiB).", + "node_actor_handles_capacity": { + "description": "Retained actor handles per node connection (default 16384, 1..=65536).", "type": [ "integer", "null" @@ -2283,17 +2057,17 @@ "format": "uint", "minimum": 0.0 }, - "request_connection_window_bytes": { - "description": "HTTP/2 connection window of a request connection (default 16 MiB).", + "node_actor_inbound_capacity": { + "description": "Events, KV and SQLite requests queued from one actor on a node connection (default 128, 1..=65536).", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint", "minimum": 0.0 }, - "request_connections": { - "description": "Connections per peer for unary requests, each carrying one peer channel (default 4).", + "node_actor_lane_capacity": { + "description": "Commands and tunnel messages queued toward one actor on a node connection (default 128, 1..=65536).", "type": [ "integer", "null" @@ -2301,8 +2075,8 @@ "format": "uint", "minimum": 0.0 }, - "request_stream_window_bytes": { - "description": "HTTP/2 stream window this worker grants a peer channel's replies (default 4 MiB). A worker's server grants each incoming stream a fixed 4 MiB window.", + "node_connect_admission_burst": { + "description": "node connects one process can admit in a burst; the budget starts full (default 400, 1..=1000000).", "type": [ "integer", "null" @@ -2310,8 +2084,8 @@ "format": "uint32", "minimum": 0.0 }, - "stream_connection_window_bytes": { - "description": "HTTP/2 connection window of a stream connection (default 32 MiB).", + "node_connect_admissions_per_second": { + "description": "node connects one process admits per second once its burst is spent (default 200, 1..=100000). A connect past the budget is closed at once with `node.connect_overloaded` and a retry hint, before any work, so a fleet reconnecting after an outage cannot overwhelm guard.", "type": [ "integer", "null" @@ -2319,32 +2093,26 @@ "format": "uint32", "minimum": 0.0 }, - "stream_connections": { - "description": "Connections per peer for long-lived streams such as tunnels (default 2).", + "node_connect_retry_after_ms": { + "description": "Retry hint sent with a shed node connect. The node waits between one and two hints, so shed connects return spread out, and caps the hint at 5 s so a shed node still retries well inside the lost threshold. The same hint goes with a connect refused because storage could not register the node yet. Unit is in milliseconds (default 1000, 100..=5000).", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "stream_stream_window_bytes": { - "description": "HTTP/2 stream window of a long-lived stream (default 1 MiB).", + "node_directory_cache_ms": { + "description": "Maximum age of the process-local node directory that actor allocation reads instead of listing the node index on every allocation. Must be greater than 0.\n\nUnit is in milliseconds. Defaults to 1000.", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint64", "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "Pegboard": { - "type": "object", - "properties": { - "actor_index_buckets_per_name": { - "description": "Hashed index bucket volumes for each namespace and actor name (default 8, 1..=256).\n\nThis is part of the index address format. Changing it on a running cluster strands existing rows in buckets that listing and destroy no longer target, so treat it as fixed per cluster.", + }, + "node_directory_max_stale_ms": { + "description": "Maximum age of a node directory listing that allocation still uses while one background listing replaces it. Allocation waits for a listing only past this age. Must be at least `node_directory_cache_ms`.\n\nUnit is in milliseconds. Defaults to 5000.", "type": [ "integer", "null" @@ -2352,17 +2120,17 @@ "format": "uint64", "minimum": 0.0 }, - "actor_index_list_concurrency": { - "description": "Maximum actor index bucket pages one listing reads at once (default 32).", + "node_event_delivery_timeout_ms": { + "description": "Time a lifecycle event may spend retrying storage command deadlines before its node socket is closed for reconnection. Defaults to 120000 ms.", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "actor_index_reaper_max_concurrency": { - "description": "Lazy orphan deletes an actor listing runs at once (default 16).", + "node_index_reaper_max_concurrency": { + "description": "Stale node row deletes one reader runs at once (default 8).", "type": [ "integer", "null" @@ -2370,8 +2138,8 @@ "format": "uint", "minimum": 0.0 }, - "actor_index_reaper_max_pending": { - "description": "Rows an actor listing's lazy orphan deletes may queue at once (default 1024).", + "node_index_reaper_max_pending": { + "description": "Stale node row deletes one reader may queue at once (default 256).", "type": [ "integer", "null" @@ -2379,8 +2147,8 @@ "format": "uint", "minimum": 0.0 }, - "actor_key_cache_capacity": { - "description": "Actor key reservations and key epochs cached in one process, each (default 100000). Reservations never change, so a cached one is kept until evicted.", + "node_lost_threshold": { + "description": "How long a disconnected node keeps its actors before stopping them, advertised to the node on connect. The engine waits as long after a connection closes before it judges the node's actors lost, so both sides agree. It must exceed the node client's longest reconnect backoff (30 s), or an engine restart stops every actor.\n\nUnit is in milliseconds (default 40000).", "type": [ "integer", "null" @@ -2388,49 +2156,34 @@ "format": "uint64", "minimum": 0.0 }, - "actor_start_notice_timeout_ms": { - "description": "Timeout of one start notice to a waiting gateway worker. Unit is in milliseconds (default 2000, 100..=30000).", + "node_ping_timeout": { + "description": "Max time since last pong before the node connection is terminated. Unit is in milliseconds.", "type": [ "integer", "null" ], - "format": "uint64", - "minimum": 0.0 + "format": "int64" }, - "actor_start_waiters_capacity": { - "description": "Gateway workers one actor keeps waiting for its start (default 64, 1..=1024). A request that finds the list full waits on its fallback poll alone.", + "node_record_cache_capacity": { + "description": "node records cached for routing fallbacks in one process (default 10000).", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint64", "minimum": 0.0 }, - "command_concurrency": { - "description": "Per-class handler concurrency for the Depot commands pegboard registers on storage workers.", - "default": { - "actor": null, - "actor_event": null, - "actor_read": null, - "index": null - }, - "allOf": [ - { - "$ref": "#/definitions/CommandConcurrency" - } - ] - }, - "envoy_actor_inbound_capacity": { - "description": "Events, KV and SQLite requests queued from one actor on an Envoy connection (default 128, 1..=65536).", + "node_record_cache_ms": { + "description": "Lifetime of a cached node record read on a routing fallback, in milliseconds (default 2000).", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "envoy_actor_lane_capacity": { - "description": "Commands and tunnel messages queued toward one actor on an Envoy connection (default 128, 1..=65536).", + "node_socket_queue_capacity": { + "description": "Messages queued for one node socket writer (default 128, 1..=65536).", "type": [ "integer", "null" @@ -2438,26 +2191,26 @@ "format": "uint", "minimum": 0.0 }, - "envoy_connect_admission_burst": { - "description": "Envoy connects one process can admit in a burst; the budget starts full (default 400, 1..=1000000).", + "node_start_wait_ms": { + "description": "Longest time a node connection holds a gateway request for an actor generation whose start command it has not forwarded yet, in milliseconds (default 1000). A gateway sends a request right behind the start, so this keeps the request from reaching the node first. When it runs out the request is forwarded anyway, and the node refuses it as not found.", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint64", "minimum": 0.0 }, - "envoy_connect_admissions_per_second": { - "description": "Envoy connects one process admits per second once its burst is spent (default 200, 1..=100000). A connect past the budget is closed at once with `envoy.connect_overloaded` and a retry hint, before any work, so a fleet reconnecting after an outage cannot overwhelm guard.", + "node_tunnel_queue_capacity": { + "description": "Messages queued toward one gateway tunnel stream on a node connection (default 128, 1..=65536).", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint", "minimum": 0.0 }, - "envoy_connect_retry_after_ms": { - "description": "Retry hint sent with a shed Envoy connect. The Envoy waits between one and two hints, so shed connects return spread out, and caps the hint at 5 s so a shed runner still retries well inside the lost threshold. The same hint goes with a connect refused because storage could not register the Envoy yet. Unit is in milliseconds (default 1000, 100..=5000).", + "node_update_ping_interval": { + "description": "Ping interval for node updates in milliseconds.", "type": [ "integer", "null" @@ -2465,8 +2218,8 @@ "format": "uint64", "minimum": 0.0 }, - "envoy_directory_cache_ms": { - "description": "Maximum age of the process-local Envoy directory that actor allocation reads instead of listing the Envoy index on every allocation. Must be greater than 0.\n\nUnit is in milliseconds. Defaults to 1000.", + "sqlite_remote_idle_ms": { + "description": "Idle time after which a remote SQL session is closed and reopened on next use.\n\nUnit is in milliseconds (default 30000).", "type": [ "integer", "null" @@ -2474,44 +2227,48 @@ "format": "uint64", "minimum": 0.0 }, - "envoy_directory_max_stale_ms": { - "description": "Maximum age of an Envoy directory listing that allocation still uses while one background listing replaces it. Allocation waits for a listing only past this age. Must be at least `envoy_directory_cache_ms`.\n\nUnit is in milliseconds. Defaults to 5000.", + "sqlite_remote_max_response_bytes": { + "description": "Largest response, in logical bytes, that one remote SQL request may return. A larger result fails the request instead of being sent.\n\nUnit is in bytes (default 25165824, 24 MiB; at most 64 MiB).", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint", "minimum": 0.0 }, - "envoy_event_delivery_timeout_ms": { - "description": "Time a lifecycle event may spend retrying storage command deadlines before its Envoy socket is closed for reconnection. Defaults to 120000 ms.", + "sqlite_remote_worker_threads": { + "description": "Threads shared by every remote SQL session in this process (default 4).", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint", "minimum": 0.0 }, - "envoy_index_reaper_max_concurrency": { - "description": "Stale Envoy row deletes one reader runs at once (default 8).", + "sqlite_server_prefetch": { + "description": "Sends SQLite pages the client is likely to read next along with the pages it asked for (default true). When off, the engine sends only requested pages but keeps maintaining its prefetch hints, so turning it back on needs no rebuild. Runtime configurable.", "type": [ - "integer", + "boolean", "null" - ], - "format": "uint", - "minimum": 0.0 + ] }, - "envoy_index_reaper_max_pending": { - "description": "Stale Envoy row deletes one reader may queue at once (default 256).", + "sqlite_sessions": { + "description": "Maximum actor storage lanes retained by one node connection (default 4000). Explicit overrides must be positive; each lane retains its database volume until stop.", "type": [ "integer", "null" ], "format": "uint", "minimum": 0.0 - }, - "envoy_lost_checks_capacity": { - "description": "Lost checks one process holds for closed Envoy connections that may not reconnect (default 4096, 1..=65536). When full, the check due soonest is dropped and its actors are found lost on their next request.", + } + }, + "additionalProperties": false + }, + "ProcessClassCapacity": { + "description": "The process-wide caps of a class that travels on unreserved subjects.", + "type": "object", + "properties": { + "incoming_capacity": { "type": [ "integer", "null" @@ -2519,238 +2276,47 @@ "format": "uint", "minimum": 0.0 }, - "envoy_lost_threshold": { - "description": "How long a disconnected Envoy keeps its actors before stopping them, advertised to the Envoy on connect. The engine waits as long after a connection closes before it judges the Envoy's actors lost, so both sides agree. It must exceed the Envoy client's longest reconnect backoff (30 s), or an engine restart stops every actor.\n\nUnit is in milliseconds (default 40000).", + "outgoing_capacity": { "type": [ "integer", "null" ], - "format": "int64" + "format": "uint", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "PubSub": { + "description": "Exact-subject worker requests and streams.", + "type": "object", + "properties": { + "classes": { + "description": "Per-class request caps. Every class has a defined cap; omitted values use the defaults.", + "anyOf": [ + { + "$ref": "#/definitions/RequestClasses" + }, + { + "type": "null" + } + ] }, - "envoy_ping_timeout": { - "description": "Max time since last pong before the envoy connection is terminated. Unit is in milliseconds.", + "max_message_bytes": { "type": [ "integer", "null" ], - "format": "int64" + "format": "uint", + "minimum": 0.0 }, - "envoy_record_cache_capacity": { - "description": "Envoy records cached for routing fallbacks in one process (default 10000).", + "max_request_subjects": { + "description": "Maximum concurrently reserved request subjects with isolated capacity.", "type": [ "integer", "null" ], - "format": "uint64", - "minimum": 0.0 - }, - "envoy_record_cache_ms": { - "description": "Lifetime of a cached Envoy record read on a routing fallback, in milliseconds (default 2000).", - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0.0 - }, - "envoy_socket_queue_capacity": { - "description": "Messages queued for one Envoy socket writer (default 128, 1..=65536).", - "type": [ - "integer", - "null" - ], - "format": "uint", - "minimum": 0.0 - }, - "envoy_start_wait_ms": { - "description": "Longest time an Envoy connection holds a gateway request for an actor generation whose start command it has not forwarded yet, in milliseconds (default 1000). A gateway sends a request right behind the start, so this keeps the request from reaching the Envoy first. When it runs out the request is forwarded anyway, and the Envoy refuses it as not found.", - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0.0 - }, - "envoy_tunnel_queue_capacity": { - "description": "Messages queued toward one gateway tunnel stream on an Envoy connection (default 128, 1..=65536).", - "type": [ - "integer", - "null" - ], - "format": "uint", - "minimum": 0.0 - }, - "envoy_update_ping_interval": { - "description": "Ping interval for envoy updates in milliseconds.", - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0.0 - }, - "gateway_port": { - "description": "Port for the new partition-backed gateway and Envoy Hyper listener (default 6422).", - "type": [ - "integer", - "null" - ], - "format": "uint16", - "minimum": 0.0 - }, - "gateway_retry_budget_max_tokens": { - "description": "Retries one gateway process can bank for a burst of refusals; the budget starts full (default 100, 0..=100000).", - "type": [ - "integer", - "null" - ], - "format": "uint32", - "minimum": 0.0 - }, - "gateway_retry_budget_percent": { - "description": "Retries of refused requests one gateway process allows, as a percentage of the requests it receives (default 10, 0..=100). A refused request past this budget fails with `guard.service_unavailable` and its retry hint, so the client owns the next attempt.", - "type": [ - "integer", - "null" - ], - "format": "uint32", - "minimum": 0.0 - }, - "gateway_start_poll_after_ms": { - "description": "Time after a gateway request starts waiting for an actor's start notice before its first fallback read. Unit is in milliseconds (default 2000, 100..=30000).", - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0.0 - }, - "gateway_start_poll_interval_ms": { - "description": "Time between later fallback reads while a gateway request waits for an actor's start. Unit is in milliseconds (default 2000, 100..=30000).", - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0.0 - }, - "gateway_start_waits_capacity": { - "description": "Actors one gateway process waits on at once for a start notice (default 65536, 1..=1048576). When full, a new request waits on its fallback poll alone.", - "type": [ - "integer", - "null" - ], - "format": "uint", - "minimum": 0.0 - }, - "gateway_websocket_open_timeout_ms": { - "description": "Time an actor WebSocket upgrade may wait for its actor, as while storage recovers after an engine restart. Past it the gateway accepts the upgrade and closes it with `guard.service_unavailable` and a retry hint, so a client without a connect timeout retries instead of waiting forever. Unit is in milliseconds (default 15000, 1000..=45000).", - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0.0 - }, - "sqlite_remote_idle_ms": { - "description": "Idle time after which a remote SQL session is closed and reopened on next use.\n\nUnit is in milliseconds (default 30000).", - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0.0 - }, - "sqlite_remote_max_response_bytes": { - "description": "Largest response, in logical bytes, that one remote SQL request may return. A larger result fails the request instead of being sent.\n\nUnit is in bytes (default 25165824, 24 MiB; at most 64 MiB).", - "type": [ - "integer", - "null" - ], - "format": "uint", - "minimum": 0.0 - }, - "sqlite_remote_worker_threads": { - "description": "Threads shared by every remote SQL session in this process (default 4).", - "type": [ - "integer", - "null" - ], - "format": "uint", - "minimum": 0.0 - }, - "sqlite_server_prefetch": { - "description": "Sends SQLite pages the client is likely to read next along with the pages it asked for (default true). When off, the engine sends only requested pages but keeps maintaining its prefetch hints, so turning it back on needs no rebuild. Runtime configurable.", - "type": [ - "boolean", - "null" - ] - }, - "sqlite_sessions": { - "description": "Maximum SQLite actor sessions retained by one Envoy connection (default 256).", - "type": [ - "integer", - "null" - ], - "format": "uint", - "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "ProcessClassCapacity": { - "description": "The process-wide caps of a class that travels on unreserved subjects.", - "type": "object", - "properties": { - "incoming_capacity": { - "type": [ - "integer", - "null" - ], - "format": "uint", - "minimum": 0.0 - }, - "outgoing_capacity": { - "type": [ - "integer", - "null" - ], - "format": "uint", - "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "PubSub": { - "description": "Exact-subject worker requests and streams.", - "type": "object", - "properties": { - "classes": { - "description": "Per-class request caps. Every class has a defined cap; omitted values use the defaults.", - "anyOf": [ - { - "$ref": "#/definitions/RequestClasses" - }, - { - "type": "null" - } - ] - }, - "max_message_bytes": { - "type": [ - "integer", - "null" - ], - "format": "uint", - "minimum": 0.0 - }, - "max_request_subjects": { - "description": "Maximum concurrently reserved request subjects with isolated capacity.", - "type": [ - "integer", - "null" - ], - "format": "uint", + "format": "uint", "minimum": 0.0 }, "peer_transport": { @@ -2761,10 +2327,13 @@ "channel_queue_bytes": null, "channel_queue_frames": null, "channel_reply_queue_bytes": null, + "incoming_channel_capacity": null, + "outgoing_channel_capacity": null, "reply_queue_bytes": null, "request_connection_window_bytes": null, "request_connections": null, "request_stream_window_bytes": null, + "server_connection_capacity": null, "stream_connection_window_bytes": null, "stream_connections": null, "stream_stream_window_bytes": null @@ -2815,7 +2384,7 @@ "additionalProperties": false }, "RequestClasses": { - "description": "Per-class request caps. Depot classes travel on reserved subjects whose window is their incoming cap, so they take only an outgoing cap across every target.", + "description": "Per-class request caps. storage classes travel on reserved subjects whose window is their incoming cap, so they take only an outgoing cap across every target.", "type": "object", "properties": { "actor_start_notice": { @@ -2829,41 +2398,41 @@ } ] }, - "depot_coordinator": { - "description": "Depot tablet coordinator requests (default outgoing 1024).", + "gateway_http": { + "description": "Gateway HTTP tunnels (default 4096 each way).", "anyOf": [ { - "$ref": "#/definitions/SubjectClassCapacity" + "$ref": "#/definitions/ProcessClassCapacity" }, { "type": "null" } ] }, - "depot_kv_command": { - "description": "Depot KV commands (default outgoing 8192).", + "gateway_websocket": { + "description": "Gateway WebSocket tunnels, held for the socket's life (default 65536 each way).", "anyOf": [ { - "$ref": "#/definitions/SubjectClassCapacity" + "$ref": "#/definitions/ProcessClassCapacity" }, { "type": "null" } ] }, - "depot_log": { - "description": "Depot log shard requests (default outgoing 8192).", + "node_command": { + "description": "Actor commands to node connections (default 4096 each way).", "anyOf": [ { - "$ref": "#/definitions/SubjectClassCapacity" + "$ref": "#/definitions/ProcessClassCapacity" }, { "type": "null" } ] }, - "depot_stop_readiness": { - "description": "Depot stop-readiness checks (default outgoing 1024).", + "storage_coordinator": { + "description": "storage partition coordinator requests (default outgoing 1024).", "anyOf": [ { "$ref": "#/definitions/SubjectClassCapacity" @@ -2873,8 +2442,8 @@ } ] }, - "depot_volume": { - "description": "Depot volume lifecycle and filesystem requests (default outgoing 4096).", + "storage_kv_command": { + "description": "storage KV commands (default outgoing 8192).", "anyOf": [ { "$ref": "#/definitions/SubjectClassCapacity" @@ -2884,33 +2453,33 @@ } ] }, - "envoy_command": { - "description": "Actor commands to envoy connections (default 4096 each way).", + "storage_log": { + "description": "storage log shard requests (default outgoing 8192).", "anyOf": [ { - "$ref": "#/definitions/ProcessClassCapacity" + "$ref": "#/definitions/SubjectClassCapacity" }, { "type": "null" } ] }, - "gateway_http": { - "description": "Gateway HTTP tunnels (default 4096 each way).", + "storage_stop_readiness": { + "description": "storage stop-readiness checks (default outgoing 1024).", "anyOf": [ { - "$ref": "#/definitions/ProcessClassCapacity" + "$ref": "#/definitions/SubjectClassCapacity" }, { "type": "null" } ] }, - "gateway_websocket": { - "description": "Gateway WebSocket tunnels, held for the socket's life (default 65536 each way).", + "storage_volume": { + "description": "storage volume lifecycle and filesystem requests (default outgoing 4096).", "anyOf": [ { - "$ref": "#/definitions/ProcessClassCapacity" + "$ref": "#/definitions/SubjectClassCapacity" }, { "type": "null" @@ -2932,19 +2501,548 @@ "format": "uint32", "minimum": 0.0 }, - "interval_ms": { - "type": "integer", + "interval_ms": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "Runtime": { + "type": "object", + "properties": { + "force_shutdown_duration": { + "description": "Time (in seconds) after which the engine process will forcibly exit after receiving SIGTERM. Must be greater than or equal to both worker_shutdown_duration and guard_shutdown_duration. Defaults to nine minutes and 50 seconds, allowing the storage stop wait, singleton handover and teardown reserve.", + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "guard_shutdown_duration": { + "description": "Time (in seconds) to allow for guard to wait for pending requests after receiving SIGTERM. Defaults to nine minutes.", + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "worker_cpu_max": { + "description": "Adjusts worker curve around this value (in millecores, i.e. 1000 = 1 core). Is not a hard limit. When unset, uses /sys/fs/cgroup/cpu.max, and if that is unset uses total host cpu.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "worker_max_concurrent_workflows": { + "description": "Maximum concurrently running workflows of a given workflow name for the **entire cluster**.", + "type": [ + "object", + "null" + ], + "additionalProperties": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + } + }, + "worker_max_deduped_workflows_per_pull": { + "description": "Maximum deduplicated workflows considered in a single pull. Defaults to 10000.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "worker_max_wake_condition_clears_per_pull": { + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "worker_max_wake_keys_per_workflow_name_per_pull": { + "description": "Maximum wake condition keys read per workflow name in a single pull. Defaults to 20000, or 5000 for the storage compaction workflows. Set the \"default\" key to apply to all workflow names.", + "type": [ + "object", + "null" + ], + "additionalProperties": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + } + }, + "worker_max_workflows_per_pull": { + "description": "Maximum wake condition keys a worker clears when leasing workflows in a single pull. Defaults to 40000. Maximum workflows a worker attempts to lease in a single pull. Defaults to 1000.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "worker_poll_interval_ms": { + "description": "Poll interval for pulling workflows and deciding whether a short sleep stays in memory. Unit is in milliseconds. Defaults to 16000.", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "worker_shutdown_duration": { + "description": "Time (in seconds) to allow for the gasoline worker engine to stop gracefully after receiving SIGTERM. Defaults to 30 seconds.", + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "S3ObjectStoreConfig": { + "type": "object", + "required": [ + "bucket" + ], + "properties": { + "access_key_id": { + "default": null, + "type": [ + "string", + "null" + ] + }, + "bucket": { + "type": "string" + }, + "endpoint": { + "default": null, + "type": [ + "string", + "null" + ] + }, + "prefix": { + "default": null, + "type": [ + "string", + "null" + ] + }, + "region": { + "default": null, + "type": [ + "string", + "null" + ] + }, + "secret_access_key": { + "default": null, + "anyOf": [ + { + "$ref": "#/definitions/Secret" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + }, + "Secret": { + "type": "string" + }, + "StorageConfig": { + "type": "object", + "properties": { + "alarms": { + "description": "Bounded, deadline-driven volume alarm delivery.", + "default": { + "handler_timeout_ms": null, + "io_timeout_ms": null, + "max_callbacks": null, + "max_candidates": null, + "max_operations": null, + "page_size": null, + "retry_max_ms": null, + "retry_min_ms": null + }, + "allOf": [ + { + "$ref": "#/definitions/AlarmConfig" + } + ] + }, + "auto_provision_partitions": { + "description": "Creates this many partitions over this storage worker when the cluster has none, so a single-process engine serves actors without an operator. A restart finishes a run that stopped partway; partitions it did not start are left alone. Clusters with several storage workers leave it unset and run `storage partition provision` instead.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "balancing": { + "default": { + "destination_stability_ms": 60000, + "enabled": true, + "max_disk_probes": 4, + "missing_worker_ms": 120000, + "partitions_per_core": 2 + }, + "allOf": [ + { + "$ref": "#/definitions/PartitionBalancingConfig" + } + ] + }, + "bulk_read_bytes_per_sec": { + "description": "Bytes per second that bulk runs may read across every partition of this process, with a burst of a quarter second (at least 4 MiB). Bulk runs wait for their bytes; point reads never wait. Unset or 0 leaves bulk runs unpaced.", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "bulk_read_cache_blocks": { + "description": "Whether SST blocks a bulk run fetches enter the shared block cache. Defaults to true; false keeps large scans from evicting other volumes' hot blocks.", + "type": [ + "boolean", + "null" + ] + }, + "bulk_read_fetch_tasks": { + "description": "Concurrent SST block fetches inside one bulk run's scan. Defaults to 1; 0 is treated as 1.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "bulk_read_min_chunks": { + "description": "Chunk runs of at least this many chunks (4 KiB each) are read with the bulk scan settings below, as a table scan's read-ahead windows are. Unset or 0 reads every run with the normal settings.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "checkpoints": { + "default": { + "max_named_checkpoints_per_volume": 64, + "retention": null + }, + "allOf": [ + { + "$ref": "#/definitions/CheckpointConfig" + } + ] + }, + "cold_store": { + "default": { + "block_cache_bytes": null, + "compacted_sst_bytes": null, + "disk_cache_bytes": null, + "disk_cache_directory": null, + "disk_cache_on_compaction": null, + "disk_cache_on_flush": null, + "disk_cache_part_bytes": null, + "l0_max_ssts": null, + "max_concurrent_compactions": null, + "meta_cache_bytes": null, + "unflushed_budget_bytes": null + }, + "allOf": [ + { + "$ref": "#/definitions/ColdStoreConfig" + } + ] + }, + "cold_store_compression": { + "description": "Codec for SlateDB SST blocks in the cold store; defaults to `lz4`. Each SST records its own codec, so changing it keeps existing SSTs readable.", + "anyOf": [ + { + "$ref": "#/definitions/ColdStoreCompression" + }, + { + "type": "null" + } + ] + }, + "command_timeout_ms": { + "description": "Floor for every typed storage command deadline, in milliseconds. Each command keeps its own default (5 seconds generic, 30 seconds for actor storage); when set, the larger of the two bounds both the client's retry budget and the maintainer's handler timeout. Unset keeps the per-command defaults.", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "coordinator_request_capacity": { + "description": "Exact coordinator subject capacity. Defaults to 256.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "durable_max_events_per_commit": { + "description": "Most events of one durable state machine applied in one commit. Events that arrive while a commit is in flight are grouped up to this bound. Defaults to 16.", + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "endpoint_cache_capacity": { + "description": "Maximum cached endpoint hints, including missing workers. Defaults to 4096.", + "default": null, + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "filesystem": { + "default": { + "max_cache_bytes": 8388608, + "max_conflict_window_bytes": 4194304, + "max_memory_bytes": 67108864, + "max_operation_bytes": 8388608, + "max_pending_commits": 128, + "max_process_cache_bytes": 1073741824, + "max_snapshot_age_ms": 30000, + "max_snapshots": 128, + "max_transaction_age_ms": 300000, + "max_transaction_bytes": 134217728, + "max_unapplied_bytes": 268435456, + "max_value_bytes": 1048576, + "note_ttl_ms": 1000, + "request_timeout_ms": 30000 + }, + "allOf": [ + { + "$ref": "#/definitions/FilesystemConfig" + } + ] + }, + "flush_piggyback_min_bytes": { + "description": "Unflushed applied bytes at which a volume joins a partition flush another volume requested. Defaults to 16 KiB.", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "flush_stage_concurrency": { + "description": "Volume records whose old rows one partition filesystem flush reads at once while it stages. Staging excludes every other store operation of the partition. Defaults to 16.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "forks": { + "default": { + "check_grace_ms": 60000, + "materialize_batch_chunks": 1024, + "max_concurrent_materializations": 2 + }, + "allOf": [ + { + "$ref": "#/definitions/ForkConfig" + } + ] + }, + "heartbeat_gc": { + "description": "Background heartbeat reclamation; separate from membership lease expiration.", + "default": { + "batch_interval_ms": null, + "batch_size": null, + "batch_timeout_ms": null, + "delete_concurrency": null, + "pass_interval_ms": null, + "retention_ms": null + }, + "allOf": [ + { + "$ref": "#/definitions/HeartbeatGcConfig" + } + ] + }, + "idle_unload_after_ms": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "kv_commands": { + "default": { + "evicted_idle_warn_ms": null, + "max_command_bytes": null, + "max_eviction_closes": null, + "max_inflight_command_bytes": null, + "max_inflight_commands": null, + "max_open_volumes": null, + "max_worker_open_volume_bytes": null, + "max_worker_open_volumes": null, + "request_capacity": null, + "short_idle_close_ms": null, + "volume_idle_close_ms": null + }, + "allOf": [ + { + "$ref": "#/definitions/KvCommandConfig" + } + ] + }, + "learning_deadline_ms": { + "description": "How long a partition replica-set change may stay in Learning before the coordinator aborts it and the partition returns to its old members. Defaults to one hour and must be at least 45 minutes. It counts from the phase's start, not from the learner's progress, so it must outlast the membership holder wait (15 minutes) plus the copy of the largest log suffix a learner may have to catch up.", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "log_client_inflight_per_worker": { + "description": "Log shard requests a client keeps in flight to one storage worker. Later requests queue and go out together as one batch when a slot frees. Defaults to 2.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "log_directory": { + "description": "Existing directory owned by one storage process. Required when storage services start.", + "type": [ + "string", + "null" + ] + }, + "log_request_capacity": { + "description": "Exact replica subject capacity, shared by local clients and the shard. Defaults to 2048.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "log_shard": { + "description": "Optional overrides for the shard's disk, memory and operation bounds.", + "default": { + "checkpoint_bytes": null, + "checkpoint_timeout_ms": null, + "disk_read_concurrency": null, + "inbox_capacity": null, + "manifest_refresh_timeout_ms": null, + "max_admission_wait_ms": null, + "max_append_admission_wait_ms": null, + "max_batch_bytes": null, + "max_disk_bytes": null, + "max_disk_reads": null, + "max_loaded_volume_bytes": null, + "max_loaded_volumes": null, + "max_memory_bytes": null, + "max_memory_requests": null, + "max_retained_payload_bytes": null, + "max_retained_payload_bytes_per_volume": null, + "max_write_bytes": null, + "overload_retry_after_ms": null, + "preallocate_segments": null, + "recovery_timeout_ms": null, + "release_idle_payloads_after_ms": null, + "remove_segments_timeout_ms": null, + "segment_bytes": null, + "write_to_cold_at_disk_percent": null, + "write_to_disk_timeout_ms": null + }, + "allOf": [ + { + "$ref": "#/definitions/LogShardConfig" + } + ] + }, + "lookup_request_capacity": { + "description": "Concurrent topology endpoint lookups and heartbeat inspections admitted per process. Defaults to 128.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "maintainer_inbox_capacity": { + "description": "Queued events one partition maintainer accepts before it rejects new requests as overloaded. Every volume open, read, apply and status notice for the partition passes through it, so a burst of actor starts on one partition needs room for several events per start. Must be positive. Defaults to 4096.", + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "maintainer_max_loaded_volumes": { + "description": "Volumes one partition maintainer holds loaded at once, before opens of more are refused as overloaded. A loaded volume costs about 1.8 KiB of maintainer heap, so the default of 500,000 holds under 1 GiB per partition. Must be positive.", + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "maintainer_max_queued_opens": { + "description": "Volume opens queued in one partition maintainer's inbox, not yet taken by its processing task, at which a new open is refused as overloaded at once instead of joining the inbox. Other inbox events do not count. Opens queued past this would mostly expire before admission. Must be positive. Defaults to 1024.", + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "maintainer_max_requests": { + "description": "Client requests one partition maintainer tracks at once before it rejects more as overloaded. Must be positive. Defaults to 1024.", + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "manifest_refresh_ms": { + "description": "Fallback interval for re-reading the partition manifest. Routing misses and `NotMaintainer` replies refresh it at once. Defaults to 30 seconds.", + "type": [ + "integer", + "null" + ], "format": "uint64", "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "Runtime": { - "type": "object", - "properties": { - "force_shutdown_duration": { - "description": "Time (in seconds) after which the engine process will forcibly exit after receiving SIGTERM. Must be greater than or equal to both worker_shutdown_duration and guard_shutdown_duration. Defaults to 35 minutes, allowing the Depot stop wait and teardown reserve.", + }, + "max_background_cold_reads": { + "description": "Size of each background cold-read window per partition maintainer: held-image source reads for forks, replica log reads for applies, fork jobs and fork cleanup jobs are each bounded by it separately, so they never take client read slots. Defaults to 4.", "type": [ "integer", "null" @@ -2952,8 +3050,8 @@ "format": "uint32", "minimum": 0.0 }, - "guard_shutdown_duration": { - "description": "Time (in seconds) to allow for guard to wait for pending requests after receiving SIGTERM. Defaults to 10 minutes.", + "max_cold_reads": { + "description": "Client cold-store reads in flight per partition maintainer: session opens, lifecycle row lookups and session reads share this window. A cold wake's reads fan out through it, so a narrow window serializes them. Object storage throughput scales almost linearly to about 32 parallel GETs, and a read slot is not always a GET, so 64 keeps a cold wake's reads from waiting on slots; on the load cluster a fully cold wake took about 850 ms at 4, 430 ms at 64 and 390 ms at 512. Defaults to 64.", "type": [ "integer", "null" @@ -2961,8 +3059,17 @@ "format": "uint32", "minimum": 0.0 }, - "worker_cpu_max": { - "description": "Adjusts worker curve around this value (in millecores, i.e. 1000 = 1 core). Is not a hard limit. When unset, uses /sys/fs/cgroup/cpu.max, and if that is unset uses total host cpu.", + "max_cold_reads_per_volume": { + "description": "Client session reads of one volume a partition maintainer admits while reads of other volumes wait, so one large scan cannot hold every client cold-read slot. Slots no other volume waits for still go to that volume. Unset or 0 admits client reads in arrival order.", + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "max_read_sessions": { + "description": "Filesystem read sessions per partition maintainer. A session lives while its volume is being read and ends after `read_session_idle_ms` without a read, so this bounds how many volumes a partition serves reads for at once. Opens past it are refused as overloaded. A held session retains about 1.2 KiB of maintainer heap, so the default of 16,384 holds under 20 MiB per partition. Must be positive.", "type": [ "integer", "null" @@ -2970,58 +3077,53 @@ "format": "uint", "minimum": 0.0 }, - "worker_max_concurrent_workflows": { - "description": "Maximum concurrently running workflows of a given workflow name for the **entire cluster**.", + "membership_refresh_cooldown_ms": { + "description": "Minimum milliseconds between miss-triggered membership refresh attempts, including failures.", "type": [ - "object", + "integer", "null" ], - "additionalProperties": { - "type": "integer", - "format": "uint", - "minimum": 0.0 - } + "format": "uint64", + "minimum": 0.0 }, - "worker_max_deduped_workflows_per_pull": { - "description": "Maximum deduplicated workflows considered in a single pull. Defaults to 10000.", + "memtable_flush_throttle_ms": { + "description": "Throttle for memtable flushes that nobody urgently waits on: a pass that comes due waits up to this long, so passes that come due close together share one upload and one L0 SST. Defaults to ten seconds.", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "worker_max_wake_condition_clears_per_pull": { + "read_cursor_session_idle_ms": { + "description": "How long a session opened at the latest position stays registered after its last read, in milliseconds. An HTTP directory cursor resumes such a session between pages, and no client reopens it at its position, so a paging client keeps its cursor for this long between pages. Must be positive. Defaults to 30,000, the session lifetime.", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "worker_max_wake_keys_per_workflow_name_per_pull": { - "description": "Maximum wake condition keys read per workflow name in a single pull. Defaults to 20000, or 5000 for the depot compaction workflows. Set the \"default\" key to apply to all workflow names.", + "read_session_idle_ms": { + "description": "How long a read session stays registered after its last read, in milliseconds. Each read extends it up to the session's lifetime, and a client reopens an ended session on its next read, so sessions track volumes being read rather than volumes open. Must be positive. Defaults to 2,000.", "type": [ - "object", + "integer", "null" ], - "additionalProperties": { - "type": "integer", - "format": "uint", - "minimum": 0.0 - } + "format": "uint64", + "minimum": 0.0 }, - "worker_max_workflows_per_pull": { - "description": "Maximum wake condition keys a worker clears when leasing workflows in a single pull. Defaults to 40000. Maximum workflows a worker attempts to lease in a single pull. Defaults to 1000.", + "simulated_fs_read_cost_us": { + "description": "Simulation only: processing time each filesystem read request costs a partition maintainer, in microseconds, spent on the simulated clock so a maintainer busy with reads queues them as a loaded one does. Unset in deployments, where real processing time passes on its own.", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "worker_poll_interval_ms": { - "description": "Poll interval for pulling workflows and deciding whether a short sleep stays in memory. Unit is in milliseconds. Defaults to 16000.", + "stop_poll_ms": { + "description": "Stop-permit retry interval. Defaults to one second.", "type": [ "integer", "null" @@ -3029,74 +3131,137 @@ "format": "uint64", "minimum": 0.0 }, - "worker_shutdown_duration": { - "description": "Time (in seconds) to allow for the gasoline worker engine to stop gracefully after receiving SIGTERM. Defaults to 30 seconds.", + "stop_teardown_ms": { + "description": "Teardown budget after a stop permit or timeout. Defaults to one minute.", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint64", "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "S3ObjectStoreConfig": { - "type": "object", - "required": [ - "bucket" - ], - "properties": { - "access_key_id": { - "default": null, + }, + "stop_timeout_ms": { + "description": "Maximum coordinated stop wait from the first signal. Defaults to eight minutes.", "type": [ - "string", + "integer", "null" - ] + ], + "format": "uint64", + "minimum": 0.0 }, - "bucket": { - "type": "string" + "store_admission_scan_limit": { + "description": "Queued store items one admission pass looks at past work that cannot start yet. Work beyond it waits for the next pass. Must be positive. Defaults to 1024.", + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 }, - "endpoint": { - "default": null, + "store_max_flush_staging": { + "description": "Partition filesystem flushes one partition maintainer lets stage at once. Staging writes the flush's records into the store. Must be positive. Defaults to 1.", "type": [ - "string", + "integer", "null" - ] + ], + "format": "uint32", + "minimum": 0.0 }, - "prefix": { - "default": null, + "store_max_flush_uploads": { + "description": "Partition filesystem flushes one partition maintainer keeps in flight at once, staging or uploading; a staging flush counts because it uploads next. Must be at least `store_max_flush_staging`. Defaults to 2.", "type": [ - "string", + "integer", "null" - ] + ], + "format": "uint32", + "minimum": 0.0 }, - "region": { - "default": null, + "store_max_keyed_in_flight": { + "description": "Filesystem applies and loads one partition maintainer admits to its store at once. They run concurrently, one task each, and their replica reads stay bounded by the cold byte budget, so the cap sizes concurrency for a burst of volume creates rather than memory. Must be positive. Defaults to 256.", "type": [ - "string", + "integer", "null" - ] + ], + "format": "uint32", + "minimum": 0.0 }, - "secret_access_key": { - "default": null, + "store_volume_lock_stripes": { + "description": "Volume lock stripes of each partition filesystem store. Two volumes on one stripe serialize their store work. Must be positive. Defaults to 1024.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "store_volume_locks": { + "description": "Which store work takes volume stripes. `core` (the default) trusts the maintainer core to order applies, loads, session opens, lifecycle lookups and the flush retention publish, so they take only the partition lock; stripes then guard only checkpoint-session opens against hold releases, checkpoint deletions and sweeps. `stripes` keeps a stripe on every operation, as before.", "anyOf": [ { - "$ref": "#/definitions/Secret" + "$ref": "#/definitions/StoreVolumeLocks" }, { "type": "null" } ] + }, + "volume_client": { + "default": { + "close_after_idle_ms": null, + "max_loaded_volumes": null, + "max_requests": null, + "max_volume_key_bytes": null, + "open_timeout_ms": null, + "payload_codec": null, + "sweep_interval_ms": null + }, + "allOf": [ + { + "$ref": "#/definitions/VolumeClientConfig" + } + ] + }, + "volume_request_capacity": { + "description": "Per-subject lifecycle request capacity, isolated from other UPS traffic. Defaults to 1024.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "volume_request_timeout_ms": { + "description": "Entire lifecycle RPC budget, including route refreshes. Defaults to five seconds.", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "write_to_cold_above_bytes": { + "description": "Committed suffix threshold, default 64 MiB and maximum 256 MiB.", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "write_to_cold_after_ms": { + "description": "Cold-write age from the first unflushed entry, plus up to a tenth of it as jitter. Defaults to one minute. Storage workers require the age with its jitter to stay below `stop_timeout_ms`, so a stopping worker never waits on a slower tiering cadence than its own stop budget.", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 } }, "additionalProperties": false }, - "Secret": { - "type": "string" - }, "StoreVolumeLocks": { - "description": "Which tablet store operations take volume lock stripes.", + "description": "Which partition store operations take volume lock stripes.", "oneOf": [ { "description": "Only work the maintainer core does not order takes a stripe.", @@ -3129,45 +3294,6 @@ }, "additionalProperties": false }, - "TabletBalancingConfig": { - "description": "Static tablet placement policy; membership and lease timings remain topology-owned.", - "type": "object", - "properties": { - "destination_stability_ms": { - "description": "How long a new worker must be listed in discovery, and pass one disk probe, before the coordinator places tablets on it. Must exceed the topology worker lease plus one renewal and the takeover grace, about 35 s, so a worker that crashes soon after it first appears has left discovery before it qualifies. Startup refuses a shorter value.", - "default": 60000, - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "enabled": { - "description": "Whether the tablet coordinator places, splits and replaces tablets on its own. When disabled, the layout changes only through operator commands: a new cluster gets no first tablet until an operator creates one, and a missing worker is never replaced.", - "default": true, - "type": "boolean" - }, - "max_disk_probes": { - "description": "Maximum concurrent disk admission requests made by the tablet coordinator.", - "default": 4, - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "missing_worker_ms": { - "description": "How long an assigned worker must be missing from discovery before its replicas are replaced. Counted from when discovery drops it, which is itself one lease after its last renewal.", - "default": 120000, - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "tablets_per_core": { - "default": 2, - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - }, - "additionalProperties": false - }, "Telemetry": { "type": "object", "required": [ diff --git a/vendor/docs/examples/docs/actors-quickstart-next-js/registry.ts b/vendor/docs/examples/docs/actors-quickstart-next-js/registry.ts deleted file mode 100644 index 4afe732a..00000000 --- a/vendor/docs/examples/docs/actors-quickstart-next-js/registry.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { actor, setup } from "rivetkit"; - -export const counter = actor({ - state: { count: 0 }, - actions: { - increment: (c, x: number) => { - c.state.count += x; - c.broadcast("newCount", c.state.count); - return c.state.count; - }, - }, -}); - -export const registry = setup({ - use: { counter }, -}); diff --git a/vendor/docs/examples/docs/actors-quickstart-react/index.ts b/vendor/docs/examples/docs/actors-quickstart-react/backend/index.ts similarity index 100% rename from vendor/docs/examples/docs/actors-quickstart-react/index.ts rename to vendor/docs/examples/docs/actors-quickstart-react/backend/index.ts diff --git a/vendor/docs/examples/docs/actors-quickstart-react/Counter.tsx b/vendor/docs/examples/docs/actors-quickstart-react/frontend/Counter.tsx similarity index 85% rename from vendor/docs/examples/docs/actors-quickstart-react/Counter.tsx rename to vendor/docs/examples/docs/actors-quickstart-react/frontend/Counter.tsx index a62ee024..26aa5be7 100644 --- a/vendor/docs/examples/docs/actors-quickstart-react/Counter.tsx +++ b/vendor/docs/examples/docs/actors-quickstart-react/frontend/Counter.tsx @@ -1,16 +1,16 @@ import { createRivetKit } from "@rivetkit/react"; import { useState } from "react"; -import type { registry } from "./index"; +import type { registry } from "../backend/index"; const { useActor } = createRivetKit("http://localhost:6420"); -function Counter() { +export function Counter() { const [count, setCount] = useState(0); // Get or create a counter actor for the key "my-counter" const counter = useActor({ name: "counter", - key: ["my-counter"] + key: ["my-counter"], }); // Listen to realtime events diff --git a/vendor/docs/examples/docs/actors-quickstart-react/frontend/main.tsx b/vendor/docs/examples/docs/actors-quickstart-react/frontend/main.tsx new file mode 100644 index 00000000..a8e4ea9d --- /dev/null +++ b/vendor/docs/examples/docs/actors-quickstart-react/frontend/main.tsx @@ -0,0 +1,9 @@ +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import { Counter } from "./Counter"; + +createRoot(document.getElementById("root")!).render( + + + , +); diff --git a/vendor/docs/examples/docs/actors-versions/programmatic-version.ts b/vendor/docs/examples/docs/actors-versions/programmatic-version.ts deleted file mode 100644 index 9763d971..00000000 --- a/vendor/docs/examples/docs/actors-versions/programmatic-version.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { actor, setup } from "rivetkit"; - -const myActor = actor({ state: {}, actions: {} }); - -const registry = setup({ - use: { myActor }, - envoy: { - version: 2, - }, -}); diff --git a/vendor/docs/examples/docs/api/actors-destroy.ts b/vendor/docs/examples/docs/api/actors-destroy.ts index 7718ad8c..d76fa102 100644 --- a/vendor/docs/examples/docs/api/actors-destroy.ts +++ b/vendor/docs/examples/docs/api/actors-destroy.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; const actorId = "00000000-0000-0000-0000-000000000000"; diff --git a/vendor/docs/examples/docs/api/actors-list-names.ts b/vendor/docs/examples/docs/api/actors-list-names.ts index ce5f865f..19ca05e2 100644 --- a/vendor/docs/examples/docs/api/actors-list-names.ts +++ b/vendor/docs/examples/docs/api/actors-list-names.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; diff --git a/vendor/docs/examples/docs/api/actors-list.ts b/vendor/docs/examples/docs/api/actors-list.ts index fcca97ee..55a79fcb 100644 --- a/vendor/docs/examples/docs/api/actors-list.ts +++ b/vendor/docs/examples/docs/api/actors-list.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; diff --git a/vendor/docs/examples/docs/api/actors-reschedule.ts b/vendor/docs/examples/docs/api/actors-reschedule.ts index 3a2f9b23..3bb1a563 100644 --- a/vendor/docs/examples/docs/api/actors-reschedule.ts +++ b/vendor/docs/examples/docs/api/actors-reschedule.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; const actorId = "00000000-0000-0000-0000-000000000000"; diff --git a/vendor/docs/examples/docs/api/actors-sleep.ts b/vendor/docs/examples/docs/api/actors-sleep.ts index e1232b21..a1d07784 100644 --- a/vendor/docs/examples/docs/api/actors-sleep.ts +++ b/vendor/docs/examples/docs/api/actors-sleep.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; const actorId = "00000000-0000-0000-0000-000000000000"; diff --git a/vendor/docs/examples/docs/api/connection-actions.ts b/vendor/docs/examples/docs/api/connection-actions.ts index d90ec127..3de81cd1 100644 --- a/vendor/docs/examples/docs/api/connection-actions.ts +++ b/vendor/docs/examples/docs/api/connection-actions.ts @@ -1,5 +1,5 @@ const ws = new WebSocket( - `wss://rivet.example.com/gateway/${process.env.ACTOR_ID}/connect`, + `wss://api.rivet.dev/gateway/${process.env.ACTOR_ID}/connect`, ["rivet", "rivet_encoding.json", `rivet_token.${process.env.RIVET_TOKEN}`], ); diff --git a/vendor/docs/examples/docs/api/connection-connect.ts b/vendor/docs/examples/docs/api/connection-connect.ts index ee4bf891..88e74ed3 100644 --- a/vendor/docs/examples/docs/api/connection-connect.ts +++ b/vendor/docs/examples/docs/api/connection-connect.ts @@ -1,7 +1,7 @@ // Open a connection by actor name. The selector query parameters are the same // ones used by the HTTP endpoints; the token and encoding travel as // WebSocket subprotocols because browsers cannot set headers on an upgrade. -const url = new URL("wss://rivet.example.com/gateway/counter/connect"); +const url = new URL("wss://api.rivet.dev/gateway/counter/connect"); url.searchParams.set("rvt-namespace", process.env.RIVET_NAMESPACE!); url.searchParams.set("rvt-method", "getOrCreate"); url.searchParams.set("rvt-key", "my-counter"); diff --git a/vendor/docs/examples/docs/api/connection-errors.ts b/vendor/docs/examples/docs/api/connection-errors.ts index f8e796c7..6345825a 100644 --- a/vendor/docs/examples/docs/api/connection-errors.ts +++ b/vendor/docs/examples/docs/api/connection-errors.ts @@ -1,5 +1,5 @@ const ws = new WebSocket( - `wss://rivet.example.com/gateway/${process.env.ACTOR_ID}/connect`, + `wss://api.rivet.dev/gateway/${process.env.ACTOR_ID}/connect`, ["rivet", "rivet_encoding.json", `rivet_token.${process.env.RIVET_TOKEN}`], ); diff --git a/vendor/docs/examples/docs/api/connection-events.ts b/vendor/docs/examples/docs/api/connection-events.ts index 71ad178a..7e85c61b 100644 --- a/vendor/docs/examples/docs/api/connection-events.ts +++ b/vendor/docs/examples/docs/api/connection-events.ts @@ -1,5 +1,5 @@ const ws = new WebSocket( - `wss://rivet.example.com/gateway/${process.env.ACTOR_ID}/connect`, + `wss://api.rivet.dev/gateway/${process.env.ACTOR_ID}/connect`, ["rivet", "rivet_encoding.json", `rivet_token.${process.env.RIVET_TOKEN}`], ); diff --git a/vendor/docs/examples/docs/api/control-plane-datacenters.ts b/vendor/docs/examples/docs/api/control-plane-datacenters.ts index 6f14c5eb..d5afca6c 100644 --- a/vendor/docs/examples/docs/api/control-plane-datacenters.ts +++ b/vendor/docs/examples/docs/api/control-plane-datacenters.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const token = process.env.RIVET_TOKEN ?? ""; const response = await fetch(`${endpoint}/datacenters`, { diff --git a/vendor/docs/examples/docs/api/control-plane-metadata.ts b/vendor/docs/examples/docs/api/control-plane-metadata.ts index ea784880..43300b91 100644 --- a/vendor/docs/examples/docs/api/control-plane-metadata.ts +++ b/vendor/docs/examples/docs/api/control-plane-metadata.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const response = await fetch(`${endpoint}/metadata`); const metadata = await response.json(); diff --git a/vendor/docs/examples/docs/api/gateway-metadata.ts b/vendor/docs/examples/docs/api/gateway-metadata.ts index 95da90f4..d677d2dd 100644 --- a/vendor/docs/examples/docs/api/gateway-metadata.ts +++ b/vendor/docs/examples/docs/api/gateway-metadata.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const response = await fetch( `${endpoint}/gateway/${process.env.ACTOR_ID}/metadata`, { diff --git a/vendor/docs/examples/docs/api/gateway-queue.ts b/vendor/docs/examples/docs/api/gateway-queue.ts index 73f95114..8d6a2aa6 100644 --- a/vendor/docs/examples/docs/api/gateway-queue.ts +++ b/vendor/docs/examples/docs/api/gateway-queue.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const actorId = process.env.ACTOR_ID; const response = await fetch(`${endpoint}/gateway/${actorId}/queue/increment`, { method: "POST", diff --git a/vendor/docs/examples/docs/api/inspector-action.ts b/vendor/docs/examples/docs/api/inspector-action.ts deleted file mode 100644 index ac8aca2c..00000000 --- a/vendor/docs/examples/docs/api/inspector-action.ts +++ /dev/null @@ -1,14 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/action/increment`, - { - method: "POST", - headers: { - Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ args: [1] }), - }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-connections.ts b/vendor/docs/examples/docs/api/inspector-connections.ts deleted file mode 100644 index cebb890d..00000000 --- a/vendor/docs/examples/docs/api/inspector-connections.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/connections`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-database-execute.ts b/vendor/docs/examples/docs/api/inspector-database-execute.ts deleted file mode 100644 index 0786a92e..00000000 --- a/vendor/docs/examples/docs/api/inspector-database-execute.ts +++ /dev/null @@ -1,17 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/database/execute`, - { - method: "POST", - headers: { - Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ - sql: "SELECT * FROM users WHERE id = ?", - args: ["user-123"], - }), - }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-database-rows.ts b/vendor/docs/examples/docs/api/inspector-database-rows.ts deleted file mode 100644 index a21e1be3..00000000 --- a/vendor/docs/examples/docs/api/inspector-database-rows.ts +++ /dev/null @@ -1,12 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const query = new URLSearchParams({ - table: "users", - limit: "100", - offset: "0", -}); -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/database/rows?${query}`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-database-schema.ts b/vendor/docs/examples/docs/api/inspector-database-schema.ts deleted file mode 100644 index e6d5acdc..00000000 --- a/vendor/docs/examples/docs/api/inspector-database-schema.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/database/schema`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-queue-delete.ts b/vendor/docs/examples/docs/api/inspector-queue-delete.ts deleted file mode 100644 index 748c1b4c..00000000 --- a/vendor/docs/examples/docs/api/inspector-queue-delete.ts +++ /dev/null @@ -1,10 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/queue`, - { - method: "DELETE", - headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` }, - }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-queue-get.ts b/vendor/docs/examples/docs/api/inspector-queue-get.ts deleted file mode 100644 index a55ec407..00000000 --- a/vendor/docs/examples/docs/api/inspector-queue-get.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/queue?limit=50`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-queue-post.ts b/vendor/docs/examples/docs/api/inspector-queue-post.ts deleted file mode 100644 index d5c71989..00000000 --- a/vendor/docs/examples/docs/api/inspector-queue-post.ts +++ /dev/null @@ -1,14 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/queue`, - { - method: "POST", - headers: { - Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ name: "increment", body: { amount: 1 } }), - }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-rpcs.ts b/vendor/docs/examples/docs/api/inspector-rpcs.ts deleted file mode 100644 index 356e615e..00000000 --- a/vendor/docs/examples/docs/api/inspector-rpcs.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/rpcs`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-state-get.ts b/vendor/docs/examples/docs/api/inspector-state-get.ts deleted file mode 100644 index 783deb57..00000000 --- a/vendor/docs/examples/docs/api/inspector-state-get.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/state`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-state-patch.ts b/vendor/docs/examples/docs/api/inspector-state-patch.ts deleted file mode 100644 index 36ef34dc..00000000 --- a/vendor/docs/examples/docs/api/inspector-state-patch.ts +++ /dev/null @@ -1,14 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/state`, - { - method: "PATCH", - headers: { - Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ state: { count: 2 } }), - }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-summary.ts b/vendor/docs/examples/docs/api/inspector-summary.ts deleted file mode 100644 index 37f0f793..00000000 --- a/vendor/docs/examples/docs/api/inspector-summary.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/summary`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-traces.ts b/vendor/docs/examples/docs/api/inspector-traces.ts deleted file mode 100644 index 9a3c1a62..00000000 --- a/vendor/docs/examples/docs/api/inspector-traces.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/traces?startMs=0&limit=100`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-workflow-history.ts b/vendor/docs/examples/docs/api/inspector-workflow-history.ts deleted file mode 100644 index 64d289d0..00000000 --- a/vendor/docs/examples/docs/api/inspector-workflow-history.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/workflow-history`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-workflow-replay.ts b/vendor/docs/examples/docs/api/inspector-workflow-replay.ts deleted file mode 100644 index 3bf3cdc8..00000000 --- a/vendor/docs/examples/docs/api/inspector-workflow-replay.ts +++ /dev/null @@ -1,14 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/workflow/replay`, - { - method: "POST", - headers: { - Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ entryId: "entry-123" }), - }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/namespaces-create.ts b/vendor/docs/examples/docs/api/namespaces-create.ts index c2f92ff5..3bda46bc 100644 --- a/vendor/docs/examples/docs/api/namespaces-create.ts +++ b/vendor/docs/examples/docs/api/namespaces-create.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const token = process.env.RIVET_TOKEN ?? ""; const response = await fetch(`${endpoint}/namespaces`, { diff --git a/vendor/docs/examples/docs/api/namespaces-list.ts b/vendor/docs/examples/docs/api/namespaces-list.ts index 5b598685..34700884 100644 --- a/vendor/docs/examples/docs/api/namespaces-list.ts +++ b/vendor/docs/examples/docs/api/namespaces-list.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const token = process.env.RIVET_TOKEN ?? ""; const response = await fetch(`${endpoint}/namespaces`, { diff --git a/vendor/docs/examples/docs/api/pools-delete.ts b/vendor/docs/examples/docs/api/pools-delete.ts new file mode 100644 index 00000000..ad9c5134 --- /dev/null +++ b/vendor/docs/examples/docs/api/pools-delete.ts @@ -0,0 +1,16 @@ +const endpoint = "https://api.rivet.dev"; +const namespace = process.env.RIVET_NAMESPACE ?? "default"; +const token = process.env.RIVET_TOKEN ?? ""; +const pool = process.env.RIVET_POOL ?? "default"; + +const params = new URLSearchParams({ namespace }); +const response = await fetch( + `${endpoint}/pools/${encodeURIComponent(pool)}?${params}`, + { + method: "DELETE", + headers: { Authorization: `Bearer ${token}` }, + }, +); +console.log(response.status); + +export {}; diff --git a/vendor/docs/examples/docs/api/pools-get.ts b/vendor/docs/examples/docs/api/pools-get.ts new file mode 100644 index 00000000..852a5f71 --- /dev/null +++ b/vendor/docs/examples/docs/api/pools-get.ts @@ -0,0 +1,13 @@ +const endpoint = "https://api.rivet.dev"; +const namespace = process.env.RIVET_NAMESPACE ?? "default"; +const token = process.env.RIVET_TOKEN ?? ""; +const pool = process.env.RIVET_POOL ?? "default"; + +const params = new URLSearchParams({ namespace }); +const response = await fetch( + `${endpoint}/pools/${encodeURIComponent(pool)}?${params}`, + { headers: { Authorization: `Bearer ${token}` } }, +); +console.log(await response.json()); + +export {}; diff --git a/vendor/docs/examples/docs/api/pools-list-nodes.ts b/vendor/docs/examples/docs/api/pools-list-nodes.ts new file mode 100644 index 00000000..b55c107f --- /dev/null +++ b/vendor/docs/examples/docs/api/pools-list-nodes.ts @@ -0,0 +1,14 @@ +const endpoint = "https://api.rivet.dev"; +const namespace = process.env.RIVET_NAMESPACE ?? "default"; +const token = process.env.RIVET_TOKEN ?? ""; +const pool = process.env.RIVET_POOL ?? "default"; + +const params = new URLSearchParams({ namespace }); +const response = await fetch( + `${endpoint}/pools/${encodeURIComponent(pool)}/nodes?${params}`, + { headers: { Authorization: `Bearer ${token}` } }, +); +const { nodes, pagination } = await response.json(); +console.log(nodes, pagination.cursor); + +export {}; diff --git a/vendor/docs/examples/docs/api/workers-configs-list.ts b/vendor/docs/examples/docs/api/pools-list.ts similarity index 52% rename from vendor/docs/examples/docs/api/workers-configs-list.ts rename to vendor/docs/examples/docs/api/pools-list.ts index 1f1c8521..eac08588 100644 --- a/vendor/docs/examples/docs/api/workers-configs-list.ts +++ b/vendor/docs/examples/docs/api/pools-list.ts @@ -1,12 +1,12 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; const params = new URLSearchParams({ namespace }); -const response = await fetch(`${endpoint}/runner-configs?${params}`, { +const response = await fetch(`${endpoint}/pools?${params}`, { headers: { Authorization: `Bearer ${token}` }, }); -const { runner_configs } = await response.json(); -console.log(runner_configs); +const { pools, pagination } = await response.json(); +console.log(pools, pagination.cursor); export {}; diff --git a/vendor/docs/examples/docs/api/workers-configs-upsert.ts b/vendor/docs/examples/docs/api/pools-upsert.ts similarity index 59% rename from vendor/docs/examples/docs/api/workers-configs-upsert.ts rename to vendor/docs/examples/docs/api/pools-upsert.ts index 50a37d3d..0097c1c7 100644 --- a/vendor/docs/examples/docs/api/workers-configs-upsert.ts +++ b/vendor/docs/examples/docs/api/pools-upsert.ts @@ -1,18 +1,18 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; -const workerName = process.env.RUNNER_NAME ?? "default"; +const pool = process.env.RIVET_POOL ?? "default"; const params = new URLSearchParams({ namespace }); const response = await fetch( - `${endpoint}/runner-configs/${encodeURIComponent(workerName)}?${params}`, + `${endpoint}/pools/${encodeURIComponent(pool)}?${params}`, { method: "PUT", headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", }, - body: JSON.stringify({ datacenters: { local: { normal: {} } } }), + body: JSON.stringify({ drain_on_version_upgrade: true }), }, ); console.log(await response.json()); diff --git a/vendor/docs/examples/docs/api/tokens-inspect.ts b/vendor/docs/examples/docs/api/tokens-inspect.ts index c562d121..7573b89f 100644 --- a/vendor/docs/examples/docs/api/tokens-inspect.ts +++ b/vendor/docs/examples/docs/api/tokens-inspect.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const token = process.env.RIVET_TOKEN ?? ""; // Inspect reports on the token used to authenticate the request itself. diff --git a/vendor/docs/examples/docs/api/workers-configs-delete.ts b/vendor/docs/examples/docs/api/workers-configs-delete.ts deleted file mode 100644 index cdc01d9e..00000000 --- a/vendor/docs/examples/docs/api/workers-configs-delete.ts +++ /dev/null @@ -1,13 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const namespace = process.env.RIVET_NAMESPACE ?? "default"; -const token = process.env.RIVET_TOKEN ?? ""; -const workerName = process.env.RUNNER_NAME ?? "default"; - -const params = new URLSearchParams({ namespace }); -const response = await fetch( - `${endpoint}/runner-configs/${encodeURIComponent(workerName)}?${params}`, - { method: "DELETE", headers: { Authorization: `Bearer ${token}` } }, -); -console.log(response.ok); - -export {}; diff --git a/vendor/docs/examples/docs/api/workers-configs-refresh-metadata.ts b/vendor/docs/examples/docs/api/workers-configs-refresh-metadata.ts index 337d7c97..1f1a7c02 100644 --- a/vendor/docs/examples/docs/api/workers-configs-refresh-metadata.ts +++ b/vendor/docs/examples/docs/api/workers-configs-refresh-metadata.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; const workerName = process.env.RUNNER_NAME ?? "default"; diff --git a/vendor/docs/examples/docs/api/workers-list.ts b/vendor/docs/examples/docs/api/workers-list.ts deleted file mode 100644 index 06f1d56e..00000000 --- a/vendor/docs/examples/docs/api/workers-list.ts +++ /dev/null @@ -1,12 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const namespace = process.env.RIVET_NAMESPACE ?? "default"; -const token = process.env.RIVET_TOKEN ?? ""; - -const params = new URLSearchParams({ namespace }); -const response = await fetch(`${endpoint}/envoys?${params}`, { - headers: { Authorization: `Bearer ${token}` }, -}); -const { envoys: workers, pagination } = await response.json(); -console.log(workers, pagination.cursor); - -export {}; diff --git a/vendor/docs/examples/docs/api/workers-serverless-health-check.ts b/vendor/docs/examples/docs/api/workers-serverless-health-check.ts index 860536f6..c6e0c54f 100644 --- a/vendor/docs/examples/docs/api/workers-serverless-health-check.ts +++ b/vendor/docs/examples/docs/api/workers-serverless-health-check.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; diff --git a/vendor/docs/examples/docs/cookbook-cron-jobs/daily-report.ts b/vendor/docs/examples/docs/cookbook-cron-jobs/daily-report.ts deleted file mode 100644 index c434d36c..00000000 --- a/vendor/docs/examples/docs/cookbook-cron-jobs/daily-report.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { actor } from "rivetkit"; - -export const dailyReport = actor({ - state: { lastRunAt: 0 }, - onCreate: async (c) => { - await c.cron.set({ - name: "daily-report", - expression: "0 9 * * *", - action: "runReport", - }); - }, - actions: { - runReport: (c) => { - // Do the job's work, then record the run. - c.state.lastRunAt = Date.now(); - }, - }, -}); diff --git a/vendor/docs/examples/docs/durable-streams/client.ts b/vendor/docs/examples/docs/durable-streams/client.ts new file mode 100644 index 00000000..97fdedf0 --- /dev/null +++ b/vendor/docs/examples/docs/durable-streams/client.ts @@ -0,0 +1,14 @@ +import { DurableStream } from "@durable-streams/client"; + +const stream = await DurableStream.create({ + url: "http://127.0.0.1:8642/durable-streams/v1/stream/demo", + contentType: "application/json", +}); + +await stream.append(JSON.stringify({ message: "hello" })); + +// Read from the beginning, then keep receiving new messages live +const res = await stream.stream<{ message: string }>(); +res.subscribeJson(async (batch) => { + for (const item of batch.items) console.log(item.message); +}); diff --git a/vendor/docs/examples/docs/durable-streams/create.ts b/vendor/docs/examples/docs/durable-streams/create.ts new file mode 100644 index 00000000..582ec8f2 --- /dev/null +++ b/vendor/docs/examples/docs/durable-streams/create.ts @@ -0,0 +1,11 @@ +import { DurableStream } from "@durable-streams/client"; + +// One stream per chat session +const stream = await DurableStream.create({ + url: "http://127.0.0.1:8642/durable-streams/v1/stream/chat/session-1", + contentType: "application/json", + // Delete the stream after a day with no reads or writes + ttlSeconds: 86400, +}); + +console.log("created", stream.url); diff --git a/vendor/docs/examples/docs/durable-streams/producer.ts b/vendor/docs/examples/docs/durable-streams/producer.ts new file mode 100644 index 00000000..eb2f8a16 --- /dev/null +++ b/vendor/docs/examples/docs/durable-streams/producer.ts @@ -0,0 +1,21 @@ +import { DurableStream, IdempotentProducer } from "@durable-streams/client"; + +const stream = new DurableStream({ + url: "http://127.0.0.1:8642/durable-streams/v1/stream/chat/session-1", + contentType: "application/json", +}); + +// Keep the producer ID the same across restarts. With autoClaim, a restarted +// agent takes over and the old one can no longer write. +const producer = new IdempotentProducer(stream, "agent-session-1", { + autoClaim: true, + onError: (error) => console.error("append failed", error), +}); + +for (const token of ["It's", " sunny", " today"]) { + producer.append(JSON.stringify({ token })); +} + +// Wait until every token is stored, then close the stream +await producer.flush(); +await producer.close(); diff --git a/vendor/docs/examples/docs/durable-streams/read-history.ts b/vendor/docs/examples/docs/durable-streams/read-history.ts new file mode 100644 index 00000000..457570d7 --- /dev/null +++ b/vendor/docs/examples/docs/durable-streams/read-history.ts @@ -0,0 +1,10 @@ +import { stream } from "@durable-streams/client"; + +const url = "http://127.0.0.1:8642/durable-streams/v1/stream/chat/session-1"; + +// Everything written so far, then stop +const res = await stream<{ token: string }>({ url, offset: "-1", live: false }); +const messages = await res.json(); + +console.log(messages); +console.log("read from here next:", res.offset); diff --git a/vendor/docs/examples/docs/durable-streams/read-live.ts b/vendor/docs/examples/docs/durable-streams/read-live.ts new file mode 100644 index 00000000..362854f3 --- /dev/null +++ b/vendor/docs/examples/docs/durable-streams/read-live.ts @@ -0,0 +1,14 @@ +import { stream } from "@durable-streams/client"; + +const url = "http://127.0.0.1:8642/durable-streams/v1/stream/chat/session-1"; + +// "-1" starts at the beginning. Pass a saved offset to pick up where you left off. +const savedOffset: string = "-1"; + +const res = await stream<{ token: string }>({ url, offset: savedOffset, live: "sse" }); +res.subscribeJson(async (batch) => { + for (const item of batch.items) console.log(item.token); + + // Save this to resume from the same place after a refresh + console.log("offset", batch.offset); +}); diff --git a/vendor/docs/examples/docs/durable-streams/write.ts b/vendor/docs/examples/docs/durable-streams/write.ts new file mode 100644 index 00000000..c68ab7ce --- /dev/null +++ b/vendor/docs/examples/docs/durable-streams/write.ts @@ -0,0 +1,13 @@ +import { DurableStream } from "@durable-streams/client"; + +const stream = new DurableStream({ + url: "http://127.0.0.1:8642/durable-streams/v1/stream/chat/session-1", + contentType: "application/json", +}); + +// Each append is one message +await stream.append(JSON.stringify({ token: "It's" })); +await stream.append(JSON.stringify({ token: " sunny" })); + +// Close with a final message: readers know the reply is complete +await stream.close({ body: JSON.stringify({ token: "." }) }); diff --git a/vendor/docs/examples/docs/general-edge/client.ts b/vendor/docs/examples/docs/general-edge/client.ts new file mode 100644 index 00000000..fde898f5 --- /dev/null +++ b/vendor/docs/examples/docs/general-edge/client.ts @@ -0,0 +1,12 @@ +import { createClient } from "rivetkit/client"; +import { actor, setup } from "rivetkit"; + +const example = actor({ state: {}, actions: {} }); +const registry = setup({ use: { example } }); + +const client = createClient("http://localhost:6420"); + +// Create actor in a specific region using getOrCreate +const actorHandle = client.example.getOrCreate(["my-actor"], { + createInRegion: "atl" +}); diff --git a/vendor/docs/examples/docs/general-jwt/quickstart/client.ts b/vendor/docs/examples/docs/general-jwt/quickstart/client.ts index bf78e5d5..49cbb1ed 100644 --- a/vendor/docs/examples/docs/general-jwt/quickstart/client.ts +++ b/vendor/docs/examples/docs/general-jwt/quickstart/client.ts @@ -14,7 +14,7 @@ async function fetchToken(): Promise<{ actorId: string; token: string }> { const { actorId } = await fetchToken(); const client = createClient({ - endpoint: "https://my-namespace@rivet.example.com", + endpoint: "https://rivet.example.com", namespace: "production", // Called whenever RivetKit needs a credential, including after one expires. diff --git a/vendor/docs/examples/docs/onboarding-actors/client.ts b/vendor/docs/examples/docs/onboarding-actors/client.ts new file mode 100644 index 00000000..307c6365 --- /dev/null +++ b/vendor/docs/examples/docs/onboarding-actors/client.ts @@ -0,0 +1,20 @@ +import { createClient } from "rivetkit/client"; +import type { registry } from "./index"; + +// Connect to the server from index.ts. The registry type checks every call. +const client = createClient("http://localhost:6420"); + +// Get the room keyed "general", creating it on first use. +const room = client.chatRoom.getOrCreate(["general"]); + +// Open a realtime connection and print each message as it arrives. +const connection = room.connect(); +connection.on("newMessage", (message: { sender: string; text: string }) => { + console.log(`${message.sender}: ${message.text}`); +}); + +// Send a message. The Actor saves it to SQLite before broadcasting it. +await connection.sendMessage("alice", "Hello, Rivet!"); + +// The history is still there after the Actor sleeps or restarts. +console.log(await room.getHistory()); diff --git a/vendor/docs/examples/docs/onboarding-actors/index.ts b/vendor/docs/examples/docs/onboarding-actors/index.ts new file mode 100644 index 00000000..0cf38744 --- /dev/null +++ b/vendor/docs/examples/docs/onboarding-actors/index.ts @@ -0,0 +1,43 @@ +import { actor, setup } from "rivetkit"; +import { db } from "rivetkit/db"; + +// A chat room Actor. Every room key gets its own instance with its own SQLite +// database, which survives restarts and redeploys. +export const chatRoom = actor({ + // Create the messages table the first time a room starts. + db: db({ + onMigrate: async (db) => { + await db.execute(` + CREATE TABLE IF NOT EXISTS messages ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + sender TEXT NOT NULL, + text TEXT NOT NULL + ) + `); + }, + }), + + actions: { + // Save a message, then push it to everyone connected to this room. + sendMessage: async (c, sender: string, text: string) => { + await c.db.execute( + "INSERT INTO messages (sender, text) VALUES (?, ?)", + sender, + text, + ); + + c.broadcast("newMessage", { sender, text }); + }, + + // Read the room's history, oldest first. + getHistory: async (c) => { + return (await c.db.execute( + "SELECT sender, text FROM messages ORDER BY id", + )) as { sender: string; text: string }[]; + }, + }, +}); + +// Register the Actor and start serving it on http://localhost:6420. +export const registry = setup({ use: { chatRoom } }); +registry.start(); diff --git a/vendor/docs/examples/docs/package.json b/vendor/docs/examples/docs/package.json index a0e98db3..3ddcea78 100644 --- a/vendor/docs/examples/docs/package.json +++ b/vendor/docs/examples/docs/package.json @@ -1,4 +1,5 @@ { + "license": "MIT", "name": "docs-snippets", "version": "2.0.21", "private": true, @@ -11,10 +12,7 @@ "rivetkit": "workspace:*", "@rivetkit/react": "workspace:*", "@rivetkit/engine-api-full": "workspace:*", - "@rivetkit/next-js": "workspace:*", - "@rivetkit/cloudflare-workers": "workspace:*", "@rivetkit/rivetkit-wasm": "workspace:*", - "@rivetkit/supabase": "workspace:*", "@rivetkit/effect": "workspace:*", "effect": "4.0.0", "@effect/platform-node": "4.0.0", diff --git a/vendor/docs/examples/docs/tsconfig.json b/vendor/docs/examples/docs/tsconfig.json index 498e3a9a..ee88fd1d 100644 --- a/vendor/docs/examples/docs/tsconfig.json +++ b/vendor/docs/examples/docs/tsconfig.json @@ -13,5 +13,12 @@ "jsx": "react-jsx" }, "include": ["**/*.ts", "**/*.tsx"], - "exclude": ["node_modules"] + "exclude": [ + "node_modules", + "actors-quickstart-next-js", + "general-http-server/elysia-handler.ts", + "general-http-server/hono-handler.ts", + "general-http-server/serve.ts", + "actors-actions/calling-backend.ts" + ] } From d4011f1ec977c4cacac8833fc03d8eaadc6fd58b Mon Sep 17 00:00:00 2001 From: Nathan Flurry Date: Tue, 3 Nov 2026 15:12:42 -0800 Subject: [PATCH 4/5] fix(docs): preserve restored documentation routes --- redirects.mjs | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/redirects.mjs b/redirects.mjs index 2506f479..01432d63 100644 --- a/redirects.mjs +++ b/redirects.mjs @@ -66,9 +66,7 @@ const explicitRedirects = { '/integrations/containers': '/integrations/', '/integrations/unity': '/integrations/', '/integrations/godot': '/integrations/', - // Endpoints was rewritten as the shorter Connect page; Runtime Modes folded - // into Nodes & Node Pools. - '/docs/endpoints': '/docs/connect/', + // Runtime Modes folded into Nodes & Node Pools. '/docs/runtime-modes': '/docs/nodes/', // Dead links inside dated changelog posts. Neither target ever existed, so // these point at the nearest real page rather than being rewritten in the @@ -97,10 +95,8 @@ const explicitRedirects = { // split credentials (Overview, JWTs, ACL) from in-Actor authorization. '/actors/docs/access-control': '/actors/docs/permissions/', '/docs/actors/access-control': '/actors/docs/permissions/', - // Credential docs are platform-wide, so they live in the General bundle - // rather than the Actors one. - '/actors/docs/authentication': '/docs/authentication/', - '/docs/actors/authentication': '/docs/authentication/', + // Legacy Actor authentication URLs point to the restored Actor-specific page. + '/docs/actors/authentication': '/actors/docs/authentication/', '/actors/docs/jwt': '/docs/jwt/', '/docs/actors/ephemeral-variables': '/actors/docs/state/', '/docs/actors/persistence': '/actors/docs/state/', @@ -132,6 +128,10 @@ const explicitRedirects = { '/docs/cloud/api/actors/create': '/actors/docs/', '/docs/cloud/api/routes/update': '/actors/docs/', '/docs/cloud/self-hosting/single-container': '/docs/deploy/self-host/control-plane/', + // Retired quickstart and gateway routes keep their existing inbound links. + '/actors/docs/quickstart/next-js': '/actors/docs/quickstart/react/', + '/docs/actors/quickstart/next-js': '/actors/docs/quickstart/react/', + '/docs/api/gateway/request': '/docs/api/', // Next.js client redirect (linked from homepage) '/docs/clients/next-js': '/actors/docs/clients/javascript/', // Self-hosting redirect @@ -438,7 +438,6 @@ function bundleSplitRedirects() { map['/actors/learn/a-radically-simpler-architecture'] = '/guides/a-radically-simpler-architecture/'; // The AI Agent guide was retired for the Agents docs and their guides. - map['/guides/ai-agent'] = '/guides/personal-agent/'; map['/actors/learn/ai-agent'] = '/guides/personal-agent/'; return map; } @@ -470,12 +469,7 @@ const RETIRED_PAGES = { '/docs/deploy/self-host/workers/aws-lambda': '/docs/deploy/self-host/nodes/', '/docs/deploy/self-host/workers/supabase': '/docs/deploy/self-host/nodes/', '/docs/deploy/self-host/workers/freestyle': '/docs/deploy/self-host/nodes/', - '/docs/workers': '/docs/nodes/', - '/docs/pool-configuration': '/docs/nodes/', '/docs/runtime-modes': '/docs/nodes/', - '/docs/statuses': '/actors/docs/lifecycle/', - '/docs/regions': '/docs/architecture/', - '/docs/troubleshooting': '/actors/docs/troubleshooting/', '/actors/docs/inspector-tabs': '/actors/docs/debugging/', '/docs/deploy/self-host/control-plane/rbac': '/docs/jwt/', '/docs/deploy/self-host/control-plane/performance': '/docs/benchmarking/', From 76306961c992403b5b90671b9e8009eba5496f7b Mon Sep 17 00:00:00 2001 From: "rivet-docs-sync[bot]" Date: Tue, 3 Nov 2026 23:20:48 +0000 Subject: [PATCH 5/5] docs(docs): sync from rivet-dev/rivet@ac94186 --- vendor/docs/docs/content/architecture.mdx | 50 +- vendor/docs/docs/content/authentication.mdx | 16 +- vendor/docs/docs/content/benchmarking.mdx | 24 +- vendor/docs/docs/content/cli.mdx | 230 +- vendor/docs/docs/content/connect.mdx | 40 +- vendor/docs/docs/content/debugging.mdx | 22 +- vendor/docs/docs/content/endpoints.mdx | 71 + .../docs/content/environment-variables.mdx | 8 +- vendor/docs/docs/content/jwt.mdx | 90 +- vendor/docs/docs/content/namespaces.mdx | 14 +- vendor/docs/docs/content/nodes.mdx | 2 + .../docs/docs/content/pool-configuration.mdx | 69 + vendor/docs/docs/content/regions.mdx | 23 + vendor/docs/docs/content/statuses.mdx | 18 + vendor/docs/docs/content/troubleshooting.mdx | 83 + vendor/docs/docs/content/versions.mdx | 264 +- vendor/docs/docs/content/workers.mdx | 30 + vendor/docs/docs/sidebar.json | 72 +- .../docs/engine/artifacts/config-schema.json | 3046 +++++++++-------- .../actors-quickstart-next-js/registry.ts | 16 - .../{ => backend}/index.ts | 0 .../{ => frontend}/Counter.tsx | 6 +- .../actors-quickstart-react/frontend/main.tsx | 9 + .../actors-versions/programmatic-version.ts | 10 - .../docs/examples/docs/api/actors-destroy.ts | 2 +- .../examples/docs/api/actors-list-names.ts | 2 +- vendor/docs/examples/docs/api/actors-list.ts | 2 +- .../examples/docs/api/actors-reschedule.ts | 2 +- vendor/docs/examples/docs/api/actors-sleep.ts | 2 +- .../examples/docs/api/connection-actions.ts | 2 +- .../examples/docs/api/connection-connect.ts | 2 +- .../examples/docs/api/connection-errors.ts | 2 +- .../examples/docs/api/connection-events.ts | 2 +- .../docs/api/control-plane-datacenters.ts | 2 +- .../docs/api/control-plane-metadata.ts | 2 +- .../examples/docs/api/gateway-metadata.ts | 2 +- .../docs/examples/docs/api/gateway-queue.ts | 2 +- .../examples/docs/api/inspector-action.ts | 14 - .../docs/api/inspector-connections.ts | 7 - .../docs/api/inspector-database-execute.ts | 17 - .../docs/api/inspector-database-rows.ts | 12 - .../docs/api/inspector-database-schema.ts | 7 - .../docs/api/inspector-queue-delete.ts | 10 - .../examples/docs/api/inspector-queue-get.ts | 7 - .../examples/docs/api/inspector-queue-post.ts | 14 - .../docs/examples/docs/api/inspector-rpcs.ts | 7 - .../examples/docs/api/inspector-state-get.ts | 7 - .../docs/api/inspector-state-patch.ts | 14 - .../examples/docs/api/inspector-summary.ts | 7 - .../examples/docs/api/inspector-traces.ts | 7 - .../docs/api/inspector-workflow-history.ts | 7 - .../docs/api/inspector-workflow-replay.ts | 14 - .../examples/docs/api/namespaces-create.ts | 2 +- .../docs/examples/docs/api/namespaces-list.ts | 2 +- vendor/docs/examples/docs/api/pools-delete.ts | 16 + vendor/docs/examples/docs/api/pools-get.ts | 13 + .../examples/docs/api/pools-list-nodes.ts | 14 + ...{workers-configs-list.ts => pools-list.ts} | 8 +- ...kers-configs-upsert.ts => pools-upsert.ts} | 8 +- .../docs/examples/docs/api/tokens-inspect.ts | 2 +- .../docs/api/workers-configs-delete.ts | 13 - .../api/workers-configs-refresh-metadata.ts | 2 +- vendor/docs/examples/docs/api/workers-list.ts | 12 - .../api/workers-serverless-health-check.ts | 2 +- .../docs/cookbook-cron-jobs/daily-report.ts | 18 - .../examples/docs/durable-streams/client.ts | 14 + .../examples/docs/durable-streams/create.ts | 11 + .../examples/docs/durable-streams/producer.ts | 21 + .../docs/durable-streams/read-history.ts | 10 + .../docs/durable-streams/read-live.ts | 14 + .../examples/docs/durable-streams/write.ts | 13 + .../docs/examples/docs/general-edge/client.ts | 12 + .../docs/general-jwt/quickstart/client.ts | 2 +- .../examples/docs/onboarding-actors/client.ts | 20 + .../examples/docs/onboarding-actors/index.ts | 43 + vendor/docs/examples/docs/package.json | 4 +- vendor/docs/examples/docs/tsconfig.json | 9 +- 77 files changed, 2501 insertions(+), 2174 deletions(-) create mode 100644 vendor/docs/docs/content/endpoints.mdx create mode 100644 vendor/docs/docs/content/pool-configuration.mdx create mode 100644 vendor/docs/docs/content/regions.mdx create mode 100644 vendor/docs/docs/content/statuses.mdx create mode 100644 vendor/docs/docs/content/troubleshooting.mdx create mode 100644 vendor/docs/docs/content/workers.mdx delete mode 100644 vendor/docs/examples/docs/actors-quickstart-next-js/registry.ts rename vendor/docs/examples/docs/actors-quickstart-react/{ => backend}/index.ts (100%) rename vendor/docs/examples/docs/actors-quickstart-react/{ => frontend}/Counter.tsx (85%) create mode 100644 vendor/docs/examples/docs/actors-quickstart-react/frontend/main.tsx delete mode 100644 vendor/docs/examples/docs/actors-versions/programmatic-version.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-action.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-connections.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-database-execute.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-database-rows.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-database-schema.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-queue-delete.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-queue-get.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-queue-post.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-rpcs.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-state-get.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-state-patch.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-summary.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-traces.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-workflow-history.ts delete mode 100644 vendor/docs/examples/docs/api/inspector-workflow-replay.ts create mode 100644 vendor/docs/examples/docs/api/pools-delete.ts create mode 100644 vendor/docs/examples/docs/api/pools-get.ts create mode 100644 vendor/docs/examples/docs/api/pools-list-nodes.ts rename vendor/docs/examples/docs/api/{workers-configs-list.ts => pools-list.ts} (52%) rename vendor/docs/examples/docs/api/{workers-configs-upsert.ts => pools-upsert.ts} (59%) delete mode 100644 vendor/docs/examples/docs/api/workers-configs-delete.ts delete mode 100644 vendor/docs/examples/docs/api/workers-list.ts delete mode 100644 vendor/docs/examples/docs/cookbook-cron-jobs/daily-report.ts create mode 100644 vendor/docs/examples/docs/durable-streams/client.ts create mode 100644 vendor/docs/examples/docs/durable-streams/create.ts create mode 100644 vendor/docs/examples/docs/durable-streams/producer.ts create mode 100644 vendor/docs/examples/docs/durable-streams/read-history.ts create mode 100644 vendor/docs/examples/docs/durable-streams/read-live.ts create mode 100644 vendor/docs/examples/docs/durable-streams/write.ts create mode 100644 vendor/docs/examples/docs/general-edge/client.ts create mode 100644 vendor/docs/examples/docs/onboarding-actors/client.ts create mode 100644 vendor/docs/examples/docs/onboarding-actors/index.ts diff --git a/vendor/docs/docs/content/architecture.mdx b/vendor/docs/docs/content/architecture.mdx index f7a6e484..334a1240 100644 --- a/vendor/docs/docs/content/architecture.mdx +++ b/vendor/docs/docs/content/architecture.mdx @@ -4,38 +4,30 @@ description: "How object storage, the control plane, and nodes work together to skill: true --- -Rivet has three parts: **object storage** keeps Actor data, the **control plane** schedules Actors and routes requests, and **actor nodes** run your code. - - - - - BACKEND - - - Clients - Browsers, apps - - - Actor nodes - Your code - - - Control plane - Schedule, route, persist - - - Object storage - S3, GCS or Azure - - - - +Rivet has three parts: **object storage** keeps Actor data, the **control plane** schedules Actors and routes requests, and **nodes** run your code. + + + + + + + + + + + + Object storage + S3, GCS, or Azure + Control plane + Schedule, route, persist + Nodes + Your code -## Actor nodes +## Nodes -An actor node is a process running your app with the Rivet SDK, started with `registry.start()`. It opens an outbound connection to the control plane and hosts the Actors assigned to it. Nodes need no public URL or inbound port for Actor traffic. Add nodes when you need more capacity. +A node is a process running your app with the Rivet SDK, started with `registry.start()`. It opens an outbound connection to the control plane and hosts the Actors assigned to it. Nodes need no public URL or inbound port for Actor traffic. Add nodes when you need more capacity. ## Control plane @@ -55,4 +47,4 @@ A namespace separates Actors, keys, and node pools. For example, use `production ## Node pools -A node pool groups nodes by name within a namespace. Configure a pool before connecting nodes to it. A node joins the pool selected by `RIVET_POOL`, which defaults to `default`. For example, create a `gpu` pool for Actors that need GPUs alongside a `default` pool for the rest. See [Nodes & Node Pools](/docs/nodes). +A node pool groups nodes by name within a namespace. Configure a pool before connecting nodes to it. A node joins the pool selected by `RIVET_POOL`, which defaults to `default`. For example, create a `gpu` pool for Actors that need GPUs alongside a `default` pool for the rest. See [Node Pool Configuration](/docs/pool-configuration). diff --git a/vendor/docs/docs/content/authentication.mdx b/vendor/docs/docs/content/authentication.mdx index 2df9255e..eb24d290 100644 --- a/vendor/docs/docs/content/authentication.mdx +++ b/vendor/docs/docs/content/authentication.mdx @@ -1,15 +1,19 @@ --- title: "Authentication" -description: "The credentials the control plane accepts and where each one belongs." +description: "Choose credentials for a self-hosted control plane or Rivet Cloud." skill: true --- -The control plane checks credentials before serving management requests or routing Actor traffic. Application-level authorization still belongs in your Actor. See [Permissions](/actors/docs/permissions). +The control plane checks credentials before serving management requests or routing Actor traffic. Application-level authorization still belongs in your Actor. See [Authentication](/actors/docs/authentication). -## Credentials +## Self-hosted control plane -Your Rivet token is the `auth.admin_token` value in the control plane config. Your nodes and backend use it to connect, create namespaces, and manage node pools. Keep it server-side. +The configured `auth.admin_token` grants every operation in every namespace. Keep it in your backend or secret store. Use it to create namespaces and issue [scoped JWTs](/docs/jwt) for applications. -For browser clients, issue [scoped JWTs](/docs/jwt). A JWT grants access to one namespace and an explicit set of resources and operations, so give each client only the permissions it needs. +A JWT grants access to one namespace and an explicit set of resources and operations. Give browser clients only the permissions they need, and keep tokens that can register nodes or manage pools on your backend. -Pass credentials in `Authorization: Bearer `, or use an [endpoint URL](/docs/connect) such as `https://production:@rivet.mycompany.com`. +Pass credentials in `Authorization: Bearer `, or use an [endpoint URL](/docs/endpoints) such as `https://production:@rivet.mycompany.com`. + +## Rivet Cloud + +Get your namespace endpoints and credentials from the [Rivet Cloud dashboard](https://dashboard.rivet.dev). Keep secret credentials on your backend. See [Rivet Cloud](/docs/deploy/cloud/) for managed deployment and token settings. diff --git a/vendor/docs/docs/content/benchmarking.mdx b/vendor/docs/docs/content/benchmarking.mdx index 1fbba5a8..2d9a776f 100644 --- a/vendor/docs/docs/content/benchmarking.mdx +++ b/vendor/docs/docs/content/benchmarking.mdx @@ -17,7 +17,7 @@ These measurements come from the October 25, 2026 Rivet Actors benchmark. Use th | **Software** | Debian 13, Node.js 24, release builds | | **Object storage** | Azure Blob Storage in the same region, with locally redundant storage (LRS) | -Requests use plain HTTP inside the region over reused connections, with one request in flight. Create and wake requests have 20 ms gaps. Each row reports all successful samples from its condition, with nearest-rank percentiles and no trimming. All conditions below completed without errors. +Requests use plain HTTP inside the region over reused connections, with one request in flight. Create and wake requests have 20 ms gaps. The warm-read condition has 1,000 warmups; inserts run without gaps. Each row reports all successful samples from its condition, with nearest-rank percentiles and no trimming. All conditions below completed without errors. ## Results @@ -29,6 +29,12 @@ Milliseconds, p50 / p99. | **Wake** | 1,200 | 4.37 | 6.80 | Client send to full ping reply from a Rivet Actor asleep for at least 10 seconds. | | **Durable insert** | 1,200 | 0.69 | 0.80 | One 128-byte SQLite row inserted in autocommit mode. Timed around the query on the node, including the write to a majority of disks across zones. | | **Warm read** | 1,200 | 0.059 | 0.080 | A primary-key read of one 128-byte row from SQLite's memory cache, timed around the query. | +| **Random read after sleep, 50 MB database** | 1,200 | 1.33 | 100.1 | First random point read after at least 13 seconds asleep. Timed around the query, with two network page fetches. | +| **Random read after sleep, 1 GB database** | 1,024 | 41.8 | 168.4 | The same condition with three network page fetches. | + +The query interval includes the SQLite call, transport, and materializing the result on the node. It excludes the client's HTTP round trip. Full HTTP p50 is 0.59 ms for a warm read, 17.8 ms for the 50 MB read after sleep, and 61.6 ms for the 1 GB read after sleep, including wake time. + +The node reaches the control plane in its own zone for reads; durable writes require a cross-zone acknowledgement. Sleeping does not guarantee a cold object-storage read. This setup tests replicated writes across zones, but its LRS bucket does not test object-storage availability during a zone failure. ## Reproducing it @@ -36,19 +42,25 @@ Milliseconds, p50 / p99. -Run three control plane instances on VMs in three zones of one region, each on raw local NVMe, with a bucket in the same region. Follow the [VM](/docs/deploy/self-host/control-plane/vm/) guide. Kubernetes does not give pods raw NVMe, so it cannot reproduce these numbers. +Run three control plane instances in three zones of one region, each on local NVMe, with a bucket in the same region. Follow the [Kubernetes](/docs/deploy/self-host/control-plane/kubernetes/) or [VM](/docs/deploy/self-host/control-plane/vm/) guide. -Run one node in the first zone, with a Rivet Actor that has a `ping` action and a SQLite table, and a load generator on the same machine. See [Deploy nodes](/docs/deploy/self-host/nodes/). +Run one node in the first zone, with a Rivet Actor that has a `ping` action and a SQLite table, and a load generator on the same machine. See [Deploy nodes](/docs/deploy/self-host/workers/). + + + + + +For the warm-read condition, seed one 128-byte row and run 1,000 reads before recording samples. Keep startup and warmup measurements separate from measured requests. -Use the sample counts and pacing above, with a new key for each create. For wakes, explicitly sleep each Actor and wait at least 10 seconds. +Use the sample counts and pacing above, with a new key for each create. For wakes, explicitly sleep each Actor and wait at least 10 seconds. For random reads, seed 128-byte rows into databases of the stated sizes, sleep the Actors for at least 13 seconds, and verify each measured query fetches pages over the network. Record HTTP and query intervals separately. @@ -59,3 +71,7 @@ Sort the successful samples and take nearest-rank percentiles. Report the sample
+ +## Under load + +These latency results use one request at a time. Concurrent create workloads that overlapped mass teardown produced timeouts. Unpaced 10 MiB writes produced errors, and a seven-minute write run slowed substantially. Measure sustained throughput and error rates for your workload separately from these latency conditions. diff --git a/vendor/docs/docs/content/cli.mdx b/vendor/docs/docs/content/cli.mdx index d052b5b7..633fda57 100644 --- a/vendor/docs/docs/content/cli.mdx +++ b/vendor/docs/docs/content/cli.mdx @@ -1,10 +1,13 @@ --- title: "CLI" -description: "Use the optional Rivet CLI to deploy to a Rivet Cloud cluster, read its logs, and call the Rivet Cloud API." +seoTitle: "Rivet CLI Documentation" +description: "Use the optional Rivet CLI to deploy Rivet Actors to Rivet Cloud and manage Rivet Cloud projects and clusters." skill: true --- -The `rivet` CLI (`@rivetkit/cli`) is optional. It deploys your app to a [Rivet Cloud](/docs/deploy/cloud/) cluster. Run it with your package manager: +The `rivet` CLI (`@rivetkit/cli`) is optional. You only need it to deploy to Rivet Cloud with `rivet deploy` and to manage Rivet Cloud projects and clusters. + +Run it with your package runner: ```bash npx @rivetkit/cli @@ -13,27 +16,70 @@ npx @rivetkit/cli | Command | Description | | --- | --- | | `rivet login` | Sign in to Rivet Cloud in the browser. | -| `rivet link` | Link the current directory to a cluster. | -| `rivet deploy` | Build and deploy your app to a cluster. | -| `rivet cluster logs` | Read or follow a cluster's logs. | +| `rivet link` | Link the current directory to a project or cluster. | +| `rivet deploy` | Build and deploy the project to Rivet Cloud. | +| `rivet logs` | Read or follow a project's compute logs. | +| `rivet pool` | List or delete compute pools in a namespace. | +| `rivet cluster logs` | Read or follow a cluster's engine and runner logs. | | `rivet api` | Make an authenticated request to the Rivet Cloud API. | +| `rivet engine` | Run the bundled `rivet-engine` binary directly. | +| `rivet setup-ci` | Install the GitHub Actions deploy workflow. | +| `rivet token` | Mint a namespace-scoped token. | ## Signing in and linking -`rivet login` opens a browser to sign in and stores the session in `~/.rivet/credentials`, refreshing it as needed. Pass `--no-browser` to print the sign-in URL instead. `rivet logout` removes the session and `rivet whoami` shows the signed-in account and linked cluster. +`rivet login` opens a browser to sign in and stores the session in `~/.rivet/credentials`, refreshing it as needed. Pass `--no-browser` to print the sign-in URL instead. `rivet logout` removes the session and `rivet whoami` shows the signed-in account and linked project. ```bash rivet login +rivet link # pick an organization and project rivet link --org my-org --cluster my-cluster ``` -`rivet link` writes `.rivet/project.json` in the current directory, so later commands there default to that cluster. It prompts for anything not passed as a flag. `rivet unlink` removes the link. +`rivet link` writes `.rivet/project.json` in the current directory, so later commands there default to that project or cluster. It prompts for anything not passed as a flag. `rivet unlink` removes the link. -Every command resolves its token in this order: `--token`, `RIVET_CLOUD_TOKEN`, then the `rivet login` session. Use `--token` or `RIVET_CLOUD_TOKEN` in CI. `--cluster` (or `RIVET_CLUSTER`) selects the cluster, with `--org` (or `RIVET_ORG`) naming the organization it belongs to. `--cloud-api` points at a different Cloud API endpoint. +Every command that talks to Rivet Cloud resolves its token in this order: `--token`, `RIVET_CLOUD_TOKEN`, the `rivet login` session, then a token saved by an earlier `rivet deploy --token`. Use `--token` or `RIVET_CLOUD_TOKEN` in CI. The project comes from `--project` and `--org` (or `RIVET_PROJECT` and `RIVET_ORG`). Otherwise an API token names its own project, and a `rivet login` session uses the linked directory or prompts for one. `--cluster` (or `RIVET_CLUSTER`) selects a cluster instead, with `--org` naming the organization it belongs to. `--cloud-api` points at a different Cloud API endpoint. ## `rivet deploy` -The CLI builds the image, uploads it as a build, rolls the pool out to that build, and prints the build ID. +Builds and pushes your project's Docker image and upserts the managed pool, printing the dashboard URL. Deploys target the `default` pool unless you pass `--pool`; a new pool is created on first deploy. See [Deploying to Rivet Cloud](/docs/deploy/self-host/control-plane). + +```bash +rivet deploy +``` + +A token passed with `--token` is saved to `~/.rivet/credentials`, so later deploys can omit it. + +| Flag | Default | Description | +| --- | --- | --- | +| `--token` | env / credentials | Rivet Cloud API token. | +| `--namespace` | `production` | Cloud namespace. | +| `--pool` | `default` | Compute pool to deploy to. | +| `--project` / `--org` | from token | Override project/org. | +| `--dockerfile` | `Dockerfile` | Dockerfile to build. | +| `--build-context` | `.` | Docker build context. | +| `--env KEY=VAL` | — | Environment override, repeatable. | +| `--image` | project slug | Image repository name. | +| `--tag` | git short SHA | Image tag. | +| `--yes` | — | Skip prompts. | +| `--reuse-image` | — | Keep the pool's current image and skip the Docker build and push. Use it to change resources without a rebuild. | + +The pool's resources and scaling are set with these flags. Each one left out keeps its server-side default. + +| Flag | Server default | Description | +| --- | --- | --- | +| `--cpu` | `1` | vCPUs per actor: `1`, `2`, `4`, `8`, or a value from `0.08` to below `1` with at most two decimals. | +| `--memory` | `512Mi` | Memory per actor, from `512Mi` to `4Gi`. | +| `--min-scale` | `0` | Actors kept running, `0` to `100`. | +| `--max-scale` | `1` | Most actors to scale to, `1` to `5000`. | +| `--max-concurrent-actors` | `1000` | Most actors the pool runs at once, `1` to `50000`. | +| `--instance-request-concurrency` | `80` | Concurrent requests per actor instance, `1` to `500`. | +| `--drain-grace-period` | `1800` | Seconds a draining instance waits for its actors to finish, `5` to `3200`. | +| `--drain-on-version-upgrade` | `true` | Drain instances on the old version when a new one deploys. Pass `--drain-on-version-upgrade=false` to disable. | + +### Deploying to a cluster + +Pass `--cluster` to deploy to a cluster instead of a project. The CLI builds the image, uploads it as a build, rolls the pool out to that build, and prints the build ID. ```bash rivet deploy --cluster my-cluster --org my-org @@ -49,7 +95,7 @@ rivet deploy --cluster my-cluster --build | Flag | Default | Description | | --- | --- | --- | -| `--cluster` | `RIVET_CLUSTER` / linked cluster | Cluster to deploy to. | +| `--cluster` | `RIVET_CLUSTER` / linked cluster | Cluster to deploy to instead of a project. | | `--org` | `RIVET_ORG` / linked organization | Organization the cluster belongs to. | | `--region` | the cluster's only region | Region of the pool. Required when the cluster has several regions. | | `--pool` | `default` | Pool to roll out. | @@ -59,34 +105,7 @@ rivet deploy --cluster my-cluster --build | `--image` | cluster name | Image name recorded on the build. | | `--tag` | git short SHA | Image tag recorded on the build. | -The saved image must be 5 GiB or smaller. See [Actor Nodes](/docs/deploy/cloud/compute) for what the image needs. - -## `rivet cluster logs` - -Prints a cluster's most recent control plane and node logs, oldest first. `-f` keeps following new lines. `--source engine` selects control plane logs and `--source runner` selects node logs. - -```bash -rivet cluster logs --cluster my-cluster -rivet cluster logs --cluster my-cluster --severity error -n 50 -rivet cluster logs --cluster my-cluster --source runner --pool default --contains timeout -f -``` - -Each line shows its timestamp, severity, source, and message. This format is not stable; pass `--json` to print one JSON object per line with `id`, `timestamp`, `severity`, `message`, `source`, `runner_pool`, and `instance_id`. - -| Flag | Default | Description | -| --- | --- | --- | -| `--cluster` | `RIVET_CLUSTER` / linked cluster | Cluster to read. Required. | -| `--source` | both | `engine` for the control plane or `runner` for nodes. | -| `--pool` | all pools | Only this node pool's logs. Cannot be combined with `--source engine`. | -| `--severity` | all | Only lines at this severity or above: `trace`, `debug`, `info`, `warn`, `error`, or `fatal`. | -| `--contains` | none | Only lines containing this text, case-insensitive. | -| `-n`, `--limit` | `100` | Number of recent lines to print first, up to 1000. | -| `-f`, `--follow` | none | Keep printing new lines as they arrive. | -| `--before` | none | Page back: only lines older than this line `id` from `--json` output. | -| `--json` | none | Emit JSON lines instead of formatted output. | -| `--token`, `--org`, `--cloud-api` | none | Same as `rivet deploy`. | - -Lines can arrive up to a minute late, and `--follow` prints them when they do. +The saved image must be 5 GiB or smaller. `--namespace`, `--env`, `--reuse-image`, and the resource and scaling flags apply to projects only and are rejected for a cluster. `rivet pool`, `rivet logs`, and `rivet token` do not support clusters. Read a cluster's logs with [`rivet cluster logs`](#rivet-cluster-logs). ## `rivet api` @@ -98,7 +117,7 @@ rivet api '/v2/clusters/{cluster}/builds' rivet api '/v2/clusters/{cluster}/builds/' -X DELETE ``` -The path is sent as written. `rivet api /v2/openapi.json` lists every endpoint. `{cluster}` and `{org}` are filled from the matching flag or the linked directory. +The path is sent as written, so `/v2/...` paths reach API v2 and unprefixed paths reach API v1. Each API serves its OpenAPI spec, which lists every endpoint: `rivet api /v2/openapi.json` for API v2 and `rivet api /doc` for API v1. `{cluster}`, `{org}`, and `{project}` are filled from the matching flag or the linked directory. Fields become a JSON body, and the method defaults to `POST` when a body is given. With `-X GET`, fields are sent as query parameters. @@ -118,3 +137,136 @@ rivet api '/v2/clusters/{cluster}/regions/us-east4/runner-pools/default' -X PUT | `--token`, `--cloud-api` | Same as `rivet deploy`. | The command exits with a non-zero status when the API responds with an error, after printing the response body. + +## `rivet logs` + +Prints a project's compute logs for one pool, oldest first. `-f` follows new lines live. For a cluster, use [`rivet cluster logs`](#rivet-cluster-logs). + +```bash +rivet logs +rivet logs --pool workers --contains error -n 200 +rivet logs --region us-east4 -f +``` + +| Flag | Default | Description | +| --- | --- | --- | +| `--namespace` | `production` | Cloud namespace. | +| `--pool` | `default` | Compute pool. | +| `--region` | all | Regions to include, comma-separated. | +| `--contains` | — | Only lines containing this text, case-insensitive. | +| `-n`, `--limit` | `100` | Number of history lines. Ignored with `--follow`. | +| `-f`, `--follow` | — | Keep printing new lines as they arrive. | +| `--before` | — | Page back: only lines before this ISO 8601 timestamp. | +| `--json` | — | Emit JSON lines instead of formatted output. | +| `--token`, `--project`, `--org` | — | See [Signing in and linking](#signing-in-and-linking). | + +## `rivet pool` + +Manages the compute pools in a namespace. A namespace can hold multiple pools; `default` is the one used when a `deploy` or `logs` command omits `--pool`. + +### `rivet pool list` + +```bash +rivet pool list +``` + +Each pool is printed as a status line (colorized by status) followed by its config (display name, image, resources, environment) and any error. Colors are disabled when stdout is not a terminal or `NO_COLOR` is set. This human-readable format is not stable; pass `--json` for machine-readable output. + +| Flag | Default | Description | +| --- | --- | --- | +| `--token` | env / credentials | Rivet Cloud API token. | +| `--namespace` | `production` | Cloud namespace. | +| `--project` / `--org` | from token | Override project/org. | +| `--json` | — | Emit raw JSON instead of formatted output. | +| `--with-env-vars` | — | Include environment variable values, which are secret and omitted otherwise. | + +### `rivet pool delete` + +Tears down a compute pool, then waits until it is fully removed, printing status changes as it goes. Prompts for confirmation unless `--yes` is passed, and refuses to run without confirmation when stdin is not a terminal. + +```bash +rivet pool delete --yes +``` + +| Flag | Default | Description | +| --- | --- | --- | +| `--namespace` | `production` | Cloud namespace the pool belongs to. | +| `--yes` | — | Skip the confirmation prompt. | +| `--token` | env / credentials | Rivet Cloud API token. | +| `--project` / `--org` | from token | Override project/org. | + +## `rivet cluster logs` + +Prints a cluster's most recent engine and runner logs, oldest first. `-f` keeps following new lines. Use `rivet logs` for a project's logs instead. + +```bash +rivet cluster logs --cluster my-cluster +rivet cluster logs --cluster my-cluster --severity error -n 50 +rivet cluster logs --cluster my-cluster --source runner --pool default --contains timeout -f +``` + +Each line shows its timestamp, severity, source (`engine`, or `runner/`), and message. This format is not stable; pass `--json` to print one JSON object per line with `id`, `timestamp`, `severity`, `message`, `source`, `runner_pool`, and `instance_id`. + +| Flag | Default | Description | +| --- | --- | --- | +| `--cluster` | `RIVET_CLUSTER` / linked cluster | Cluster to read. Required. | +| `--source` | both | `engine` or `runner`. | +| `--pool` | all pools | Only this runner pool's logs. Cannot be combined with `--source engine`. | +| `--severity` | all | Only lines at this severity or above: `trace`, `debug`, `info`, `warn`, `error`, or `fatal`. | +| `--contains` | — | Only lines containing this text, case-insensitive. | +| `-n`, `--limit` | `100` | Number of recent lines to print first, up to 1000. | +| `-f`, `--follow` | — | Keep printing new lines as they arrive. | +| `--before` | — | Page back: only lines older than this line `id` from `--json` output. | +| `--json` | — | Emit JSON lines instead of formatted output. | +| `--token`, `--org`, `--cloud-api` | — | Same as `rivet deploy`. | + +Lines can arrive up to a minute late, and `--follow` prints them when they do. + +## `rivet engine` + +Runs the bundled `rivet-engine` binary directly. Arguments are forwarded verbatim. + +```bash +rivet engine nuke # wipe local engine state +rivet engine wf list # inspect workflows +``` + +## `rivet setup-ci` + +Installs `.github/workflows/rivet-deploy.yml`, which deploys to Rivet Cloud on push and pull request. Add `--force` to overwrite. Then set the token secret: + +```bash +gh secret set RIVET_CLOUD_TOKEN +``` + +## `rivet token` + +Mints a namespace-scoped token for connecting to Rivet. Only the token is printed to stdout, so it can be captured directly by scripts (e.g. `TOKEN=$(rivet token create --kind secret)`). + +```bash +rivet token create --kind secret +``` + +| `--kind` | Prefix | Use | +| --- | --- | --- | +| `secret` | `sk_` | Server-side runner/runtime token. | +| `public` | `pk_` | Client token: resolve and manage actors. | +| `connection` | `ck_` | Client token limited to resolving actors and opening connections. | + +By default the namespace must already exist. Pass `--create-namespace` to create it first (useful for per-branch CI namespaces). + +| Flag | Default | Description | +| --- | --- | --- | +| `--kind` | _(required)_ | Token kind: `secret`, `public`, or `connection`. | +| `--namespace` | `production` | Cloud namespace. | +| `--create-namespace` | — | Create the namespace if it does not exist. | +| `--token` | env / credentials | Rivet Cloud API token. | +| `--project` / `--org` | from token | Override project/org. | + +## Engine binary resolution + +`rivet engine` resolves the `rivet-engine` binary from, in order: `--engine-binary`, `RIVET_ENGINE_BINARY_PATH`, a binary bundled next to the CLI, a local `target/{debug,release}` build, then an auto-downloaded release. Set `RIVETKIT_ENGINE_AUTO_DOWNLOAD=0` to require a local binary. + +## Related + +- [Deploying to Rivet Cloud](/docs/deploy/self-host/control-plane) diff --git a/vendor/docs/docs/content/connect.mdx b/vendor/docs/docs/content/connect.mdx index e71e630b..b6024eae 100644 --- a/vendor/docs/docs/content/connect.mdx +++ b/vendor/docs/docs/content/connect.mdx @@ -8,11 +8,31 @@ skill: true No configuration is needed. RivetKit runs a local control plane on your machine. -## Production +RivetKit runs Rivet Actors entirely on your machine. Configure `RIVET_ENDPOINT` when connecting to a separate control plane. ### Private endpoint -The private endpoint tells your nodes and backend where the control plane is. It carries a secret token, so keep it server-side. +Everything that talks to Rivet is configured with one URL, the Rivet endpoint. It carries three pieces of information: + +``` +https://:@api.rivet.dev +``` + +- **Host**: The control plane to connect to. Rivet Cloud is `api.rivet.dev`. Self-hosted deployments use their own host. +- **Namespace**: The isolated environment your Actors live in, such as `production` or `staging`. See [Namespaces](/docs/namespaces). +- **Token**: Authenticates the connection and scopes it to that namespace. The token prefix tells you where it is safe to use: + +| Prefix | Kind | Where it lives | +| --- | --- | --- | +| `sk_` | Secret | Your backend and workers only. Full access to the namespace. | +| `pk_` | Public | Browsers and mobile apps. Can resolve, create, and connect to Actors. | +| `ck_` | Connection | Browsers and mobile apps. Can only resolve Actors and open connections. | + +Create tokens in the dashboard under your namespace. + +## Connect Your Backend + +Set `RIVET_ENDPOINT` with a secret token wherever your workers run. This is the only setting most deployments need. @@ -34,13 +54,13 @@ RIVET_ENDPOINT=https://my-namespace:@rivet.example.com ## URL auth syntax -Endpoint URLs carry the namespace and token: +Clients reach your Actors through the control plane's gateway, never through your backend directly. Point them at the same endpoint with a public token instead of a secret one. -``` -https://namespace:token@host/path -``` +Pass the public endpoint directly when constructing a [JavaScript](/actors/docs/clients/javascript), [React](/actors/docs/clients/react), [Swift](/actors/docs/clients/swift), or [Rust](/actors/docs/clients/rust) client. + +## URL Auth Syntax -This is the recommended form. Alternatively, set them separately: +Embedding the namespace and token in the URL is the recommended form because it is one value to manage. If your platform cannot store credentials inside a URL, the same three values can be set separately: ```bash RIVET_ENDPOINT=https://rivet.example.com @@ -48,7 +68,11 @@ RIVET_NAMESPACE=my-namespace RIVET_TOKEN= ``` -On a self-hosted control plane, use your [namespace slug](/docs/namespaces) and your Rivet token, the `auth.admin_token` value from the control plane config. For the `default` namespace: `https://default:@rivet.example.com`. +| Environment Variable | Config Option | Description | +| --- | --- | --- | +| `RIVET_ENDPOINT` | `endpoint` | Control plane URL for your backend | +| `RIVET_NAMESPACE` | `namespace` | Namespace to run Actors in | +| `RIVET_TOKEN` | `token` | Token for the backend connection | ## Reference diff --git a/vendor/docs/docs/content/debugging.mdx b/vendor/docs/docs/content/debugging.mdx index e8fc9cb3..470f2b6a 100644 --- a/vendor/docs/docs/content/debugging.mdx +++ b/vendor/docs/docs/content/debugging.mdx @@ -18,7 +18,7 @@ export RIVET_TOKEN="" # export RIVET_API="http://localhost:6420" RIVET_NAMESPACE="default" RIVET_TOKEN="default" ``` -Send the token as a bearer token on every request except `GET /metadata`. Use a token authorized for the selected namespace. On a self-hosted control plane, your Rivet token works in every namespace. See [Namespaces](/docs/namespaces). +Send the token as a bearer token on every request except `GET /metadata`. Use a token authorized for the selected namespace. The self-hosted admin token can access every namespace. See [Namespaces](/docs/namespaces). ## Rivet Actors @@ -38,7 +38,7 @@ curl "$RIVET_API/actors?actor_ids=id1,id2&namespace=$RIVET_NAMESPACE" \ -H "Authorization: Bearer $RIVET_TOKEN" ``` -When `actor_ids` is set, `name` and `key` are ignored. +`actor_ids` cannot be combined with `name` or `key`. ```json { @@ -55,7 +55,7 @@ When `actor_ids` is set, `name` and `key` are ignored. } ``` -Keys in HTTP requests separate components with `/`, escaping `/` and `\` inside a component with a backslash. An empty component is `\0`. For example, the key `["chat", "42"]` is `chat/42`. Use `curl --get --data-urlencode` for keys containing special characters. The single-component key `my-key` needs no escaping. +Keys in HTTP requests use comma-separated components, with commas and backslashes escaped inside a component. Use `curl --get --data-urlencode` for keys containing special characters. The single-component key `my-key` needs no escaping. ### Create a Rivet Actor @@ -68,7 +68,9 @@ curl -X PUT "$RIVET_API/actors?namespace=$RIVET_NAMESPACE" \ -d '{ "name": "my-actor", "key": "my-key" }' ``` -The Rivet Actor runs in the `default` [node pool](/docs/nodes). +The Rivet Actor runs in the `default` node pool. + +Set `"pool": "gpu"` in the request body to select another configured [node pool](/docs/pool-configuration). ### Sleep or destroy a Rivet Actor @@ -85,7 +87,6 @@ curl -X DELETE "$RIVET_API/actors/{actor_id}?namespace=$RIVET_NAMESPACE" \ ```bash curl "$RIVET_API/actors/names?namespace=$RIVET_NAMESPACE" \ -H "Authorization: Bearer $RIVET_TOKEN" -``` ## Nodes @@ -99,8 +100,15 @@ curl "$RIVET_API/pools?namespace=$RIVET_NAMESPACE" \ -H "Authorization: Bearer $RIVET_TOKEN" ``` -Pool configuration persists even when no nodes are connected. See [Nodes & Node Pools](/docs/nodes#read-pools-and-nodes). +Pool configuration persists even when no nodes are connected. + +To check that nodes are connected, call a Rivet Actor from a client. A Rivet Actor stays **Pending** while no node in its node pool is connected. See [Statuses](/docs/statuses). + +## OpenAPI Spec + +An OpenAPI specification covering many of the management and actor endpoints is available: -## API reference +- In the repository at [`rivetkit-openapi/openapi.json`](https://github.com/rivet-dev/rivet/tree/main/rivetkit-openapi) +- Served at `/doc` when running locally Every control plane endpoint, with its parameters and responses, is listed in the [HTTP API reference](/docs/api). diff --git a/vendor/docs/docs/content/endpoints.mdx b/vendor/docs/docs/content/endpoints.mdx new file mode 100644 index 00000000..516bb2e3 --- /dev/null +++ b/vendor/docs/docs/content/endpoints.mdx @@ -0,0 +1,71 @@ +--- +title: "Endpoints" +seoTitle: "Rivet Endpoint Configuration" +description: "Configure private and public Rivet endpoints for your nodes and clients, including namespace credentials and environment variable options." +skill: true +--- + +## Local development + +No configuration is needed. RivetKit runs a local control plane on your machine. + +## Production + +### Private endpoint + +The private endpoint tells your nodes and backend where the control plane is. It carries a secret token, so keep it server-side. + + + + + +```bash +RIVET_ENDPOINT=https://my-namespace:sk_xxxxx@api.rivet.dev +``` + + + + + + + + + + + +### Public endpoint + +The public endpoint is what your app hands to browser clients. It is exposed to the internet, so use a public token (`pk_`), never a secret token (`sk_`). + +```bash +RIVET_PUBLIC_ENDPOINT=https://my-namespace:pk_xxxxx@api.rivet.dev +``` + + +## URL auth syntax + +Endpoint URLs carry the namespace and token: + +``` +https://namespace:token@host/path +``` + +This is the recommended form. Alternatively, set them separately: + +```bash +RIVET_ENDPOINT=https://api.rivet.dev +RIVET_NAMESPACE=my-namespace +RIVET_TOKEN=sk_xxxxx +``` + +On a self-hosted control plane, use your [namespace slug](/docs/namespaces) and admin token. For the `default` namespace: `https://default:@rivet.example.com`. + +## Reference + +| Environment Variable | Config Option | Description | +|---------------------|---------------|-------------| +| `RIVET_ENDPOINT` | `endpoint` | Control plane URL for your nodes and backend | +| `RIVET_NAMESPACE` | `namespace` | Namespace for Rivet Actor isolation | +| `RIVET_TOKEN` | `token` | Token for the control plane connection | +| `RIVET_PUBLIC_ENDPOINT` | | Client-facing endpoint | +| `RIVET_PUBLIC_TOKEN` | | Client-facing token | diff --git a/vendor/docs/docs/content/environment-variables.mdx b/vendor/docs/docs/content/environment-variables.mdx index 75a08495..e3665770 100644 --- a/vendor/docs/docs/content/environment-variables.mdx +++ b/vendor/docs/docs/content/environment-variables.mdx @@ -5,8 +5,7 @@ skill: true --- These variables wire your process to a Rivet control plane. Variables that -configure the RivetKit SDK itself, including logging, storage, and the -inspector, are listed in [Environment Variables](/actors/docs/environment-variables) +configure the RivetKit SDK itself, including logging and storage, are listed in [Environment Variables](/actors/docs/environment-variables) in the Actors docs. ## Connection @@ -22,8 +21,7 @@ in the Actors docs. | Environment Variable | Description | |---------------------|-------------| | `RIVET_POOL` | Node pool to join (default: "default"). See [Architecture](/docs/architecture#node-pools). | -| `RIVET_ENVOY_VERSION` | Version number of this node. Increase it on every deploy. See [Versions & Upgrades](/docs/versions#setting-the-version). | - +| `RIVET_NODE_VERSION` | Version number of this node (default: 1). Increase it on every deploy. `RIVET_ENVOY_VERSION` is still read as an older name. See [Versions & Upgrades](/docs/versions#setting-the-version). | ## Local Control Plane @@ -35,5 +33,5 @@ In development, RivetKit starts a local control plane for you. These variables o | `RIVET_RUN_ENGINE_HOST` | Host the local control plane binds to. Defaults to `127.0.0.1`. | | `RIVET_RUN_ENGINE_PORT` | Port the local control plane binds to. Defaults to `6420`. | | `RIVET_RUN_ENGINE_VERSION` | Version of the local control plane to download | -| `RIVET_RUN_SERVICES` | Set to `1` to run Services with the local control plane, or `0` to disable it. By default, Services runs whenever the local control plane does. | +| `RIVET_RUN_SERVICES` | Services starts by default when RivetKit manages a local Engine. Set to `0` to disable it. | | `RIVET_SERVICES_BINARY` | Path to a local `rivet-services` binary. | diff --git a/vendor/docs/docs/content/jwt.mdx b/vendor/docs/docs/content/jwt.mdx index 34c83bac..85b4d540 100644 --- a/vendor/docs/docs/content/jwt.mdx +++ b/vendor/docs/docs/content/jwt.mdx @@ -4,45 +4,21 @@ description: "Issue short-lived JWTs with explicit permissions in one namespace. skill: true --- -A scoped token is a JWT that gives its holder selected permissions in one namespace. Issue it on your backend with your Rivet token, using the RivetKit client or the HTTP API, then return only the scoped token to the application. +A scoped token gives its holder selected permissions in one namespace. Issue it on your backend with the control plane's admin credential, then return only the scoped token to the application. -## Issue a token +## Quickstart - - + + -Create a client on your backend with your Rivet token in the endpoint: - - - -For one Actor, call `issueToken` on its handle. Without `permissions`, the token can only send traffic to that Actor: - - - -Pass `permissions` to replace the default. The handle accepts `actor_gateway` and `actor` permissions and scopes each grant to the Actor's ID: - - - -For namespace-wide grants, such as creating Actors, call `client.auth.issueToken` with an explicit grant list: - - - -`expiresIn` is in seconds. `issuedAt` and `expiresAt` are Unix timestamps in milliseconds. - - - - -Call `POST /auth/tokens` with your Rivet token. This grants traffic to every Actor in the `production` namespace; use `{"id":""}` as the target for one Actor. +This example grants read access to Actor traffic in the `production` namespace. Every holder can reach every Actor in that namespace; use a specific Actor ID for private per-user access. ```bash -export RIVET_API=https://rivet.example.com - curl -X POST "$RIVET_API/auth/tokens" \ - -H "Authorization: Bearer $RIVET_TOKEN" \ + -H "Authorization: Bearer $RIVET_ADMIN_TOKEN" \ -H 'Content-Type: application/json' \ -d '{ "namespace": "production", - "subject": "user-123", "duration": 900, "grants": [ {"resource":"actor_gateway","target":"any","operations":["read"]} @@ -50,36 +26,22 @@ curl -X POST "$RIVET_API/auth/tokens" \ }' ``` -The response contains `token`, `issued_ts` and `expires_ts`. Timestamps are Unix milliseconds; `duration` is seconds. See [Create token](/docs/api/tokens/create). - - - +The response contains `token`, `issued_ts`, and `expires_ts`. Timestamps are Unix milliseconds; `duration` is seconds. -Return only the scoped token to the client. Never send your Rivet token to a browser. + + -## Use the token - - - - -Give the browser client a `getToken` function that asks your backend for a token. The client calls it on first use and again when the token expires. - - - - - - -Send the token as a bearer token. This request reaches the Actor's [request handler](/actors/docs/request-handler): +Set `$RIVET_TOKEN` to the returned token and call an Actor's gateway endpoint: ```bash -curl "$RIVET_API/gateway/$ACTOR_ID/request/" \ - -H "Authorization: Bearer $SCOPED_TOKEN" +curl "$RIVET_API/gateway/$ACTOR_ID/health" \ + -H "Authorization: Bearer $RIVET_TOKEN" ``` - - +This grant does not allow Actor creation, listing, node registration, or pool management. -A gateway grant does not allow Actor creation, listing, node registration or pool management. + + ## Grants @@ -92,29 +54,13 @@ Each grant names a `resource`, a `target`, and `operations` drawn from `create`, | `node` | Register or inspect nodes. | | `pool` | Read or manage node pool configuration. | -Actor management and gateway access require separate grants. Permission to reach one Actor does not allow the holder to create other Actors. Namespace administration and token issuance require your Rivet token. +Actor management and gateway access require separate grants. Permission to reach one Actor does not allow the holder to create other Actors. Namespace administration and token issuance require the admin credential. ## Inspect and renew ```bash curl "$RIVET_API/auth/tokens/inspect" \ - -H "Authorization: Bearer $SCOPED_TOKEN" -``` - -The response contains the namespace slug, grants, subject, and issue and expiry timestamps. Renew expiring credentials through your authenticated backend. Do not give clients your Rivet token to renew tokens themselves. - -## Signing keys - -The control plane signs tokens with keys it rotates automatically every 7 days. A token lasts 1 hour by default and at most 24 hours. - -To revoke every outstanding token at once, rotate the signing keys immediately. Run these on any control plane instance; they read the instance's configuration: - -```bash -rivet-engine depot jwt show -rivet-engine depot jwt emergency-rotate \ - --request-id \ - --expected-coordinator-epoch \ - --expected-ring-version + -H "Authorization: Bearer $RIVET_TOKEN" ``` -Every instance stops accepting the old tokens within 5 minutes. If the command's reply is lost, run `show` again and retry with the same request ID. +The response contains the namespace slug, grants, subject, and issue and expiry timestamps. Renew expiring credentials through your authenticated backend. Do not give clients the admin credential to renew tokens themselves. diff --git a/vendor/docs/docs/content/namespaces.mdx b/vendor/docs/docs/content/namespaces.mdx index 1d65b0f2..8c2763ea 100644 --- a/vendor/docs/docs/content/namespaces.mdx +++ b/vendor/docs/docs/content/namespaces.mdx @@ -11,11 +11,11 @@ A namespace separates Actors, Actor keys, and node pools on one control plane. E -Use your Rivet token, the `auth.admin_token` value from your control plane config: +Use your control plane's admin token: ```bash curl -X POST "$RIVET_API/namespaces" \ - -H "Authorization: Bearer $RIVET_TOKEN" \ + -H "Authorization: Bearer $RIVET_ADMIN_TOKEN" \ -H 'Content-Type: application/json' \ -d '{"name":"staging"}' ``` @@ -31,12 +31,12 @@ Create a pool in the namespace before connecting nodes: ```bash curl -X PUT "$RIVET_API/pools/default?namespace=staging" \ - -H "Authorization: Bearer $RIVET_TOKEN" \ + -H "Authorization: Bearer $RIVET_ADMIN_TOKEN" \ -H 'Content-Type: application/json' \ -d '{"metadata":{"environment":"staging"}}' ``` -See [Nodes & Node Pools](/docs/nodes) for pool settings. +See [Node Pool Configuration](/docs/pool-configuration) for pool settings. @@ -44,9 +44,11 @@ See [Nodes & Node Pools](/docs/nodes) for pool settings. Set the namespace slug in the node's private endpoint and start the registry with `registry.start()`: ```bash -RIVET_ENDPOINT=https://staging:@rivet.mycompany.com +RIVET_ENDPOINT=https://staging:@rivet.mycompany.com ``` +Use a [scoped token](/docs/deploy/self-host/control-plane/rbac/) for applications. The admin token can access every namespace. + @@ -54,7 +56,7 @@ RIVET_ENDPOINT=https://staging:@rivet.mycompany.com ```bash curl "$RIVET_API/namespaces?limit=100" \ - -H "Authorization: Bearer $RIVET_TOKEN" + -H "Authorization: Bearer $RIVET_ADMIN_TOKEN" ``` The response contains `namespaces` and `pagination.cursor`. Pass the cursor as `cursor` on the next request. Filter a single namespace with `?name=staging`. diff --git a/vendor/docs/docs/content/nodes.mdx b/vendor/docs/docs/content/nodes.mdx index aa8dfed9..135583d0 100644 --- a/vendor/docs/docs/content/nodes.mdx +++ b/vendor/docs/docs/content/nodes.mdx @@ -24,6 +24,8 @@ curl -X PUT "$RIVET_API/pools/default?namespace=$RIVET_NAMESPACE" \ The control plane refuses a node whose pool does not exist. Local development is the exception: when the endpoint is on `localhost`, RivetKit creates the pool itself. +If registration or a reconnect fails with `pool.not_found`, the node stops and reports its namespace and pool. A cached serverless runtime returns the same error and reports unhealthy until restarted. Check the configured namespace and pool, or restore the original control-plane storage before restarting the node. Recreating a pool does not restore lost Actor data. Transient connection failures still reconnect automatically. + diff --git a/vendor/docs/docs/content/pool-configuration.mdx b/vendor/docs/docs/content/pool-configuration.mdx new file mode 100644 index 00000000..58a92301 --- /dev/null +++ b/vendor/docs/docs/content/pool-configuration.mdx @@ -0,0 +1,69 @@ +--- +title: "Node Pool Configuration" +description: "Create persistent node pool configuration and connect nodes by pool name." +skill: true +--- + +A node pool groups nodes by name within a namespace. Configure the pool explicitly before connecting nodes to it. For example, use `default` for general workloads and `gpu` for Actors that need GPUs. + +## Quickstart + + + + +Set `$RIVET_API` to your control plane URL, `$RIVET_NAMESPACE` to the namespace slug, and `$RIVET_TOKEN` to a token with pool management access: + +```bash +curl -X PUT "$RIVET_API/pools/gpu?namespace=$RIVET_NAMESPACE" \ + -H "Authorization: Bearer $RIVET_TOKEN" \ + -H 'Content-Type: application/json' \ + -d '{"metadata":{"hardware":"gpu"}}' +``` + +Pool configuration persists independently of connected nodes. Repeating `PUT` updates the configuration. + + + + +Set the same namespace and pool on each node that should serve this workload: + +```bash +RIVET_ENDPOINT=https://staging:@rivet.mycompany.com +RIVET_POOL=gpu +``` + +Start your registry with `registry.start()`. Metadata describes the pool; it does not provision hardware. Run the nodes on the machines you want to use. + + + + +## Read configuration + +```bash +# One pool +curl "$RIVET_API/pools/gpu?namespace=$RIVET_NAMESPACE" \ + -H "Authorization: Bearer $RIVET_TOKEN" + +# All configured pools in the namespace +curl "$RIVET_API/pools?namespace=$RIVET_NAMESPACE" \ + -H "Authorization: Bearer $RIVET_TOKEN" +``` + +The single-pool response has a `pool` object. The list response has a `pools` array whose entries include their `name`, plus a `pagination.cursor` for the next page. A configured pool remains listed when no nodes are connected. + +## Remove a pool + +Stop its nodes before deleting its configuration: + +```bash +curl -X DELETE "$RIVET_API/pools/gpu?namespace=$RIVET_NAMESPACE" \ + -H "Authorization: Bearer $RIVET_TOKEN" +``` + +The control plane rejects deletion while nodes are connected. + +## Related + +- [Nodes](/docs/workers) +- [Namespaces](/docs/namespaces) +- [Deploy Nodes](/docs/deploy/self-host/workers/) diff --git a/vendor/docs/docs/content/regions.mdx b/vendor/docs/docs/content/regions.mdx new file mode 100644 index 00000000..09c5ab30 --- /dev/null +++ b/vendor/docs/docs/content/regions.mdx @@ -0,0 +1,23 @@ +--- +title: "Regions" +description: "Choose the region a Rivet Actor runs in on Rivet Cloud, and how regions work when you self-host." +skill: true +--- + +A Rivet Actor lives in one region for its lifetime, and its data stays in that region. + +## Region selection on Rivet Cloud + +By default, a Rivet Actor is created in the region nearest the client. Override the region at create time: + + + +See [Actor-Actor Communication](/actors/docs/communicating-between-actors) for the full set of create options. + +## Where a Rivet Actor stays + +A Rivet Actor does not move between regions. Reads and writes to its data never cross a region boundary. A call between Rivet Actors in different regions goes over the network, so treat it like any other remote call. + +## Self-hosting + +A self-hosted control plane runs in one region. Multi-region self-hosting is coming. diff --git a/vendor/docs/docs/content/statuses.mdx b/vendor/docs/docs/content/statuses.mdx new file mode 100644 index 00000000..b550e3b7 --- /dev/null +++ b/vendor/docs/docs/content/statuses.mdx @@ -0,0 +1,18 @@ +--- +title: "Actor Statuses" +description: "Understand the lifecycle statuses of Rivet Actors, what they mean, and how to troubleshoot common issues." +skill: true +--- + +## Statuses + +| Status | Description | +|---|---| +| **Starting** | The Rivet Actor has been created but is not yet accepting connections. | +| **Running** | The Rivet Actor is live and accepting connections. | +| **Sleeping** | The Rivet Actor went to sleep after a period of inactivity. It wakes automatically on the next request. | +| **Pending** | The Rivet Actor is waiting for a node. This happens when no node in its node pool is connected. See [Troubleshooting](/actors/docs/troubleshooting#actor-status-is-pending) for common causes. | +| **Crashed** | The Rivet Actor failed to start or hit a fatal error. See [Troubleshooting](/actors/docs/troubleshooting#actor-status-is-crashed) for common failure reasons. | +| **Destroyed** | The Rivet Actor was destroyed. | + +{/* TODO(code): document the status timestamps in the actor API (`create_ts` plus start, sleep and destroy times) once the control plane returns them. Today `GET /actors` returns only `create_ts`, and destroyed Rivet Actors are not listed. Also confirm whether "Crash Loop Backoff" still exists. */} diff --git a/vendor/docs/docs/content/troubleshooting.mdx b/vendor/docs/docs/content/troubleshooting.mdx new file mode 100644 index 00000000..44906a7b --- /dev/null +++ b/vendor/docs/docs/content/troubleshooting.mdx @@ -0,0 +1,83 @@ +--- +title: "Troubleshooting" +description: "Troubleshoot Rivet control plane connectivity, deployment configuration, and persistent logs with practical diagnostic checks." +skill: true +--- + +## Common Steps + +Before diving into specific errors, try these general troubleshooting steps: + +- Check your server logs for `level=ERROR` or `level=WARN` messages. +- Check if any of your backend processes have crashed or restarted unexpectedly. +- If you need more diagnostics, set `RIVET_LOG_LEVEL=DEBUG` for verbose logging. See [Logging](/actors/docs/logging) for more options. + +## Persistent logs require durable object storage + +If startup reports `storage.log_directory requires durable object_storage.primary`, configure a durable primary object store. Setting `storage.log_directory` alone persists log shards, but cluster metadata and cold data live in `object_storage.primary`. Its default, `in_memory`, loses those objects when the control plane process exits. + +For a single control plane process, set `RIVET__OBJECT_STORAGE__PRIMARY__FILE_SYSTEM__PATH` to a directory on a persistent volume. Multiple control plane processes must share a durable object store such as S3, GCS, or Azure Blob Storage. See [Storage](/docs/deploy/self-host/control-plane/storage/). + +### Missing records after a restart + +If logs report `a volume has no stored record but a replica reports a cold position above zero` and requests fail with `depot.corrupt`, the primary object store is missing data that the surviving log shards expect. This can happen after restarting with an in-memory primary store, or after pointing an existing deployment at an empty store. + +Preserve the log directory and any remaining object storage before attempting recovery. If the original durable object store still exists, check its configured location, bucket or container, and prefix. Pointing at a new empty store does not recover existing data. Storage inspection and repair cannot reconstruct cold data that has already been lost and trimmed from the log shards. Contact support with the configuration and logs before changing stored data. + +## Reporting Issues + +If you're stuck, reach out on [Discord](https://rivet.dev/discord) or file an issue on [GitHub](https://github.com/rivet-dev/rivet/issues). + +When reporting, please include: + +- **Symptoms** + - Whether this is happening in local dev, deployed, or both + - The error you're seeing (screenshot or error message) + - Relevant source code related to the issue +- **What you've tried to solve it** +- **Environment** + - RivetKit version + - Runtime (Node, Bun, etc.) including version + - If applicable, hosting platform in use (e.g. Kubernetes, Railway, AWS ECS) + - If applicable, HTTP router in use (e.g. Hono, Express, Elysia) + +## Actor status is crashed + +See [Actor Statuses](/docs/statuses) for more about this status. + +The dashboard will show the specific failure reason. Common errors include: + +### `crashed` + +The actor's `run` handler threw an unhandled exception or exited unexpectedly. Check your actor logs for the error message and stack trace. + +{/* TODO(code): list the allocation failure reasons the control plane reports for a Rivet Actor once it records them. Today only a crash in your own code is reported. */} + +### `internal_error` + +An unexpected error occurred within Rivet. If this persists, please [contact support](https://rivet.dev/actors/docs). + +## Actors crashing immediately on startup + +If your actors are being created and then immediately destroyed or crashing, there is likely an error being thrown in your `createState` or `onCreate` lifecycle hooks. These hooks run during actor initialization before the actor is marked as ready. + +Check your server logs for the error message and stack trace. Common causes include: + +- An exception thrown in `createState` (e.g. invalid input, failed validation, or a runtime error when computing initial state) +- An exception thrown in `onCreate` (e.g. a failing external API call, missing configuration, or invalid setup logic) + +Fix the error in the relevant lifecycle hook and redeploy. + +## Actors not upgrading to new code + +During a rollout, old and new nodes both run Rivet Actors until the old nodes stop. A Rivet Actor started on an old node keeps running the old code until it sleeps or its node stops. Finish the rollout by stopping every old node. See [Versions & Upgrades](/docs/versions). + +## Actor status is pending + +See [Actor Statuses](/docs/statuses) for more about this status. + +An actor stays in "pending" status while no node in its node pool is connected to accept it. + +- Check that at least one node is running and that its `RIVET_ENDPOINT` points at the right control plane and namespace. +- Check that the node joined the node pool the actor runs in. A node joins the pool named by `RIVET_POOL`, or `default`. +- Check your node logs for connection errors. diff --git a/vendor/docs/docs/content/versions.mdx b/vendor/docs/docs/content/versions.mdx index 0da41316..e2120550 100644 --- a/vendor/docs/docs/content/versions.mdx +++ b/vendor/docs/docs/content/versions.mdx @@ -1,244 +1,25 @@ --- title: "Versions & Upgrades" -description: "Version node deployments, route new Rivet Actors to current code, and drain older nodes without downtime." +description: "Roll out new code to your nodes and upgrade Rivet Actor state without downtime." skill: true --- -## How Versions Work +## Rolling out a new version -Each node has a **version number**. When you deploy new code with a new version, Rivet handles the transition automatically: +Deploy new code by rolling your nodes like any other service. When a node stops, its Rivet Actors sleep and save their state, then wake on a running node on their next request. During the rollout, old and new nodes both run Rivet Actors, so keep each deploy compatible with the state the previous one wrote. See [Upgrading Actor State](#upgrading-actor-state). -- **New actors go to the newest version**: When allocating actors, Rivet always prefers nodes with the highest version number -- **Multiple versions can coexist**: Old actors continue running on old versions while new actors are created on the new version -- **Drain old actors**: When enabled, a node connecting with a newer version number gracefully stops old actors so they are rescheduled to the new version -- **Versions only go up**: Deploying a lower version number never moves allocation back to it. To undo a bad deploy, redeploy the previous code with a new, higher version number. +### Setting the version - -Versions are not configured by default. See [Setting the Version](#setting-the-version) to configure the node version. - +Set `RIVET_NODE_VERSION` to a number that increases on every deploy. Within a node pool, new and waking Rivet Actors are only placed on nodes running the newest version that has a connected node, so as soon as the first node of a deploy connects, the previous deploy stops receiving new actors. Actors already running on older nodes keep running until those nodes stop. A version whose nodes have all disconnected is ignored, so a failed deploy does not block placement. -### Example Scenario +Without `RIVET_NODE_VERSION`, every node reports version 1 and placement spreads across all connected nodes in the pool. The version of each node is shown in the node listing API as `version`. - +### Drain on version upgrade - +Placement alone leaves Rivet Actors that never sleep on the old nodes until those nodes stop. Set `drain_on_version_upgrade` on the pool to move them as well: once a node of a newer version is connected, actors on older nodes are stopped the same way a node shutdown stops them, and they wake on the newest version on their next request. Eviction starts after `actor_eviction_delay` seconds and is paced by `actor_eviction_period` and `actor_eviction_rate`, so a large pool is not rescheduled all at once. See [Pool settings](/docs/nodes#pool-settings). -When a new version is deployed, existing actors are gracefully stopped on the old node and rescheduled onto the new version. +The older nodes stay connected and keep receiving heartbeats, but no new actors are placed on them. Rivet never exits a node process; stopping or replacing the old nodes is up to whatever runs them. If every node of the newer version disconnects, the drain stops and the older nodes serve again. A pool's settings are read when a node connects, so changing them applies to nodes that connect afterwards. -
-
- - - - - - - Node v1 - - - Node v2 - - Currently running - - Deployed - - Drain old actors - - - Reschedule actors - - - Shut down when all actors stopped - -
-
- -
- - - -When a new version is deployed, both versions coexist. New actors are created on the new version while existing actors continue running on the old version until they sleep. - -
-
- - - - Node v1 - - - Node v2 - - Currently running - - Deployed - - Actor 1 sleeps from inactivity - - Actor 1 wakes up when prompted - -
-
- -
- -
- -## Configuration - -### Setting the Version - -Configure the node version with an environment variable or in your registry setup: - - - -```bash {{"title": "Environment Variable"}} -RIVET_ENVOY_VERSION=2 -``` - - - - - - -The version **must** be set at build time, not at runtime. Do not use `Date.now()` or similar runtime values in your registry setup code. This would assign a different version every time the server starts, causing actors to be drained and rescheduled on every restart instead of only on new deployments. - - - -The version **must** increase on every deployment. Never roll a deployment back to an older version number. New actors keep going to the nodes still on the higher version, so as the rollback replaces them the set of nodes accepting actors shrinks until it reaches zero and nothing can be scheduled. Allocation only recovers once every higher-version node has disconnected and expired. To undo a bad deploy, redeploy the previous code with a new, higher version number. - - -### Example Configurations - -We recommend injecting a build-time value that increments with every deployment. Here are concrete examples for common setups: - - - - - -Generate the version at build time and bake it into the image as an environment variable: - -```bash @nocheck -docker build --build-arg RIVET_ENVOY_VERSION=$(date +%s) . -``` - -```dockerfile @nocheck -FROM node:24-slim -ARG RIVET_ENVOY_VERSION -ENV RIVET_ENVOY_VERSION=$RIVET_ENVOY_VERSION -WORKDIR /app -COPY . . -RUN npm install && npm run build -CMD ["node", "dist/server.js"] -``` - -All containers from this image will share the same version. - - - - - -Set the version in `next.config.ts`. Next.js evaluates this file once at build time and inlines the value into the bundle: - -```typescript @nocheck -import type { NextConfig } from "next"; - -const nextConfig: NextConfig = { - env: { - RIVET_ENVOY_VERSION: String(Math.floor(Date.now() / 1000)), - }, -}; - -export default nextConfig; -``` - - - - - -Use `define` in your Vite config. This is evaluated once at build time and inlined into the bundle: - -```typescript @nocheck -import { defineConfig } from "vite"; - -export default defineConfig({ - define: { - "process.env.RIVET_ENVOY_VERSION": JSON.stringify( - String(Math.floor(Date.now() / 1000)) - ), - }, -}); -``` - - - - - -Set the version from your CI pipeline: - -```yaml @nocheck -# GitHub Actions -env: - RIVET_ENVOY_VERSION: ${{ github.run_number }} -``` - -```bash @nocheck -# Railway / Render / generic CI -export RIVET_ENVOY_VERSION=$(date +%s) -``` - -```bash @nocheck -# Git commit count -export RIVET_ENVOY_VERSION=$(git rev-list --count HEAD) -``` - - - - - -Generate a version file during your build step and import it: - -```json @nocheck -{ - "scripts": { - "build": "echo \"export const BUILD_VERSION = $(date +%s);\" > src/build-version.ts && tsc" - } -} -``` - -```typescript @nocheck -import { actor, setup } from "rivetkit"; -import { BUILD_VERSION } from "./build-version"; - -const myActor = actor({ state: {}, actions: {} }); - -const registry = setup({ - use: { myActor }, - envoy: { - version: BUILD_VERSION, - }, -}); -``` - - - - - -### Drain on Version Upgrade - -The `drain_on_version_upgrade` setting on a node pool controls whether old actors are stopped when nodes with a newer version connect. Set it when you create or update the pool. See [Nodes & Node Pools](/docs/nodes) for every pool setting, including how to rate-limit actor eviction during the drain. - -```bash -curl -X PUT "$RIVET_API/pools/default?namespace=default" \ - -H "Authorization: Bearer $RIVET_TOKEN" \ - -H 'Content-Type: application/json' \ - -d '{"drain_on_version_upgrade": true}' -``` - -| Value | Behavior | -|-------|----------| -| `false` (default) | Old actors keep running. New actors go to the new version. Versions coexist. | -| `true` | Old actors sleep, saving their state, and wake on a node running the new version. | ## Upgrading Actor State @@ -274,30 +55,11 @@ Use [Zod](https://zod.dev/) to parse persisted state on wake. Zod's `.default()` For anything beyond simple defaults, consider moving to [SQLite](/actors/docs/sqlite) where you get proper migration tooling. -## Advanced - -### How Version Upgrade Detection Works - -When `drain_on_version_upgrade` is enabled and a node connects with a newer version number, the control plane drains every older node in the same pool. - -### SIGTERM Handling - -When a node process receives `SIGTERM`, it gracefully stops all of its actors before exiting: - -- Each actor's `onSleep` hook runs, giving it time to save state. -- Actors are rescheduled to other available nodes. -- If the process is killed before its actors finish stopping, for example with `SIGKILL`, the control plane reschedules them once the node is considered lost. - -Give each node at least 60 seconds between `SIGTERM` and `SIGKILL`. - -### Shutdown Timeouts +## Stopping a node -| Timeout | Default | Description | Configuration | -|---------|---------|-------------|---------------| -| `sleepGracePeriod` | 15s | Total graceful sleep budget for `onSleep`, `waitUntil`, `keepAwake`, and async raw WebSocket handlers | [Actor options](/actors/docs/lifecycle#options) | -| `envoy_lost_threshold` | 40s | How long the control plane waits before rescheduling the actors of a node that disappeared without stopping | [Control plane config](/docs/deploy/self-host/control-plane/configuration/) (`pegboard.envoy_lost_threshold`) | +When a node receives `SIGTERM`, it puts each of its Rivet Actors to sleep before exiting. Each Rivet Actor gets up to 15 seconds to save its state. If a node disappears without stopping, the control plane reschedules its Rivet Actors after 15 seconds. ## Related -- [Nodes & Node Pools](/docs/nodes): Pool settings and connecting nodes -- [Lifecycle](/actors/docs/lifecycle): Actor lifecycle hooks including `onSleep` +- [Architecture](/docs/architecture) +- [Deploy nodes](/docs/deploy/self-host/workers/) diff --git a/vendor/docs/docs/content/workers.mdx b/vendor/docs/docs/content/workers.mdx new file mode 100644 index 00000000..463bda31 --- /dev/null +++ b/vendor/docs/docs/content/workers.mdx @@ -0,0 +1,30 @@ +--- +title: "Nodes" +description: "Run your registry as a node, select a node pool, and add capacity." +skill: true +--- + +A node is a long-running process running your app with the Rivet SDK. Start it with `registry.start()`. It connects outbound to the control plane and hosts the Actors assigned to it. + +## Connect a node + +Create a [namespace](/docs/namespaces) and [node pool](/docs/pool-configuration), then set the node's connection variables: + +```bash +RIVET_ENDPOINT=https://production:@rivet.mycompany.com +RIVET_POOL=default +``` + +`RIVET_POOL` defaults to `default`. The pool must be configured in the selected namespace before the node connects. + +Actor traffic uses the outbound connection, so nodes need no public URL or inbound port. Your app can expose its own [health and metrics routes](/actors/docs/http-server#add-health-and-metrics-routes). + +## Add capacity + +Run more copies of your app with the same namespace and pool. Use your hosting platform's autoscaler to change the number of node processes. Keep spare capacity so Actors can wake while another node restarts. + +When a node stops, its Actors sleep and can wake on another node in the pool. See [Versions & Upgrades](/docs/versions) for rolling deployments. + +## Deploy + +Use the shared [node deployment guides](/docs/deploy/self-host/workers/) for Kubernetes, Docker, virtual machines, and other platforms that run a persistent process. Nodes can connect to Rivet Cloud or a self-hosted control plane. diff --git a/vendor/docs/docs/sidebar.json b/vendor/docs/docs/sidebar.json index 24dd667a..e507a9da 100644 --- a/vendor/docs/docs/sidebar.json +++ b/vendor/docs/docs/sidebar.json @@ -15,15 +15,26 @@ ] }, { - "title": "Connect", + "title": "Running Workloads", "pages": [ { - "title": "Connect", - "href": "/docs/connect" + "title": "Namespaces", + "href": "/docs/namespaces" + }, + { + "title": "Nodes", + "href": "/docs/workers" + }, + { + "title": "Node Pool Configuration", + "href": "/docs/pool-configuration" + }, + { + "title": "Endpoints", + "href": "/docs/endpoints" }, { "title": "Authentication", - "collapsible": true, "pages": [ { "title": "Overview", @@ -33,60 +44,55 @@ "title": "Scoped Tokens", "href": "/docs/jwt" } - ] + ], + "collapsible": true + }, + { + "title": "Environment Variables", + "href": "/docs/environment-variables" + }, + { + "title": "Versions & Upgrades", + "href": "/docs/versions" + }, + { + "title": "Regions", + "href": "/docs/regions" } ] }, { - "title": "Operate", + "title": "Operating", "pages": [ { - "title": "Namespaces", - "href": "/docs/namespaces" + "title": "Statuses", + "href": "/docs/statuses" }, { - "title": "Nodes & Node Pools", - "href": "/docs/nodes" + "title": "Tracing", + "href": "/docs/tracing" }, { - "title": "Versions & Upgrades", - "href": "/docs/versions" + "title": "Debugging", + "href": "/docs/debugging" }, { - "title": "Monitoring", - "collapsible": true, - "pages": [ - { - "title": "OpenTelemetry", - "href": "/docs/tracing" - }, - { - "title": "Management API", - "href": "/docs/debugging" - } - ] + "title": "Troubleshooting", + "href": "/docs/troubleshooting" } ] }, { "title": "Reference", "pages": [ - { - "title": "Environment Variables", - "href": "/docs/environment-variables" - }, { "title": "CLI", "href": "/docs/cli" }, { - "title": "API Specs", + "title": "API Reference", "collapsible": true, "pages": [ - { - "title": "HTTP API", - "href": "/docs/api" - }, { "title": "OpenAPI", "href": "https://github.com/rivet-dev/rivet/tree/main/rivetkit-openapi", diff --git a/vendor/docs/engine/artifacts/config-schema.json b/vendor/docs/engine/artifacts/config-schema.json index 2cb4c431..77abed1f 100644 --- a/vendor/docs/engine/artifacts/config-schema.json +++ b/vendor/docs/engine/artifacts/config-schema.json @@ -20,28 +20,6 @@ "auth": { "$ref": "#/definitions/Auth" }, - "compute_gateway": { - "default": null, - "anyOf": [ - { - "$ref": "#/definitions/ComputeGateway" - }, - { - "type": "null" - } - ] - }, - "depot": { - "default": null, - "anyOf": [ - { - "$ref": "#/definitions/DepotConfig" - }, - { - "type": "null" - } - ] - }, "epoxy": { "default": null, "anyOf": [ @@ -75,17 +53,6 @@ } ] }, - "metadata": { - "default": null, - "anyOf": [ - { - "$ref": "#/definitions/Metadata" - }, - { - "type": "null" - } - ] - }, "metrics": { "default": { "hardware": { @@ -101,6 +68,17 @@ } ] }, + "migrate_from_v2": { + "default": null, + "anyOf": [ + { + "$ref": "#/definitions/MigrateFromV2" + }, + { + "type": "null" + } + ] + }, "object_storage": { "default": null, "anyOf": [ @@ -164,6 +142,17 @@ } ] }, + "storage": { + "default": null, + "anyOf": [ + { + "$ref": "#/definitions/StorageConfig" + }, + { + "type": "null" + } + ] + }, "telemetry": { "default": { "enabled": true @@ -189,7 +178,7 @@ "additionalProperties": false, "definitions": { "AlarmConfig": { - "description": "Optional overrides for the tablet frontier and worker-owned callback pool.", + "description": "Optional overrides for the partition frontier and worker-owned callback pool.", "type": "object", "properties": { "handler_timeout_ms": { @@ -448,7 +437,7 @@ "minimum": 0.0 }, "disk_cache_directory": { - "description": "Directory for the local disk cache of cold-store object parts. Defaults to `cold-cache` inside `depot.log_directory`. Its contents are disposable.", + "description": "Directory for the local disk cache of cold-store object parts. Defaults to `cold-cache` inside `storage.log_directory`. Its contents are disposable.", "type": [ "string", "null" @@ -462,7 +451,7 @@ ] }, "disk_cache_on_flush": { - "description": "Writes each SST a tablet flush uploads into the disk cache as well, so its first reads are local. Defaults to true.", + "description": "Writes each SST a partition flush uploads into the disk cache as well, so its first reads are local. Defaults to true.", "type": [ "boolean", "null" @@ -478,7 +467,7 @@ "minimum": 0.0 }, "l0_max_ssts": { - "description": "L0 SSTs a tablet database holds before SlateDB stalls memtable flushes until a compaction drains them. One compaction takes up to this many sources, so it drains a full L0 at once. Higher values absorb flush bursts at the cost of more SSTs per read. Defaults to 16.", + "description": "L0 SSTs a partition database holds before SlateDB stalls memtable flushes until a compaction drains them. One compaction takes up to this many sources, so it drains a full L0 at once. Higher values absorb flush bursts at the cost of more SSTs per read. Defaults to 16.", "type": [ "integer", "null" @@ -487,7 +476,7 @@ "minimum": 0.0 }, "max_concurrent_compactions": { - "description": "Concurrent compactions per tablet database. A worker maintaining more than 8 tablets runs one per database. Defaults to 2.", + "description": "Concurrent compactions per partition database. A worker maintaining more than 8 partitions runs one per database. Defaults to 2.", "type": [ "integer", "null" @@ -505,7 +494,7 @@ "minimum": 0.0 }, "unflushed_budget_bytes": { - "description": "Unflushed memtable bytes for the whole process, split evenly across the tablets this worker maintains (at most 512 MiB and at least 8 MiB per tablet). Defaults to 1 GiB.", + "description": "Unflushed memtable bytes for the whole process, split evenly across the partitions this worker maintains (at most 512 MiB and at least 8 MiB per partition). Defaults to 1 GiB.", "type": [ "integer", "null" @@ -517,7 +506,7 @@ "additionalProperties": false }, "CommandConcurrency": { - "description": "Maximum simultaneous handlers per pegboard command class on one storage worker. Each value is further capped by `depot.kv_commands.max_inflight_commands`.", + "description": "Maximum simultaneous handlers per pegboard command class on one storage worker. Each value is further capped by `storage.kv_commands.max_inflight_commands`.", "type": "object", "properties": { "actor": { @@ -530,7 +519,7 @@ "minimum": 0.0 }, "actor_event": { - "description": "Actor state machine events, including envoy lifecycle reports. Defaults to 256.", + "description": "Actor state machine events, including node lifecycle reports. Defaults to 256.", "type": [ "integer", "null" @@ -559,29 +548,6 @@ }, "additionalProperties": false }, - "ComputeGateway": { - "type": "object", - "required": [ - "auth_token", - "cloud_url" - ], - "properties": { - "auth_token": { - "description": "Token for authenticating with the Cloud API's internal route endpoint.", - "allOf": [ - { - "$ref": "#/definitions/Secret" - } - ] - }, - "cloud_url": { - "description": "URL of the Cloud API (e.g., \"https://cloud.rivet.dev/internal/route\")", - "type": "string", - "format": "uri" - } - }, - "additionalProperties": false - }, "Datacenter": { "type": "object", "required": [ @@ -653,233 +619,201 @@ } ] }, - "DepotConfig": { + "Epoxy": { + "description": "Epoxy runs in a single datacenter with fixed membership, so it has no settings yet. The section stays so multi-region settings have a home.", + "type": "object", + "additionalProperties": false + }, + "FileSystemObjectStoreConfig": { + "description": "A local directory used by one engine process at a time. Conditional writes are atomic only among requests of that process.", "type": "object", + "required": [ + "path" + ], "properties": { - "alarms": { - "description": "Bounded, deadline-driven volume alarm delivery.", - "default": { - "handler_timeout_ms": null, - "io_timeout_ms": null, - "max_callbacks": null, - "max_candidates": null, - "max_operations": null, - "page_size": null, - "retry_max_ms": null, - "retry_min_ms": null - }, - "allOf": [ - { - "$ref": "#/definitions/AlarmConfig" - } - ] - }, - "auto_provision_tablets": { - "description": "Creates this many tablets over this storage worker when the cluster has none, so a single-node engine serves actors without an operator. A restart finishes a run that stopped partway; tablets it did not start are left alone. Clusters with several storage workers leave it unset and run `depot tablet provision` instead.", - "type": [ - "integer", - "null" - ], + "path": { + "description": "Created when it does not exist.", + "type": "string" + } + }, + "additionalProperties": false + }, + "FilesystemConfig": { + "type": "object", + "properties": { + "max_cache_bytes": { + "description": "Bytes one filesystem's row cache may retain, a fairness ceiling inside `max_process_cache_bytes`.", + "default": 8388608, + "type": "integer", "format": "uint", "minimum": 0.0 }, - "balancing": { - "default": { - "destination_stability_ms": 60000, - "enabled": true, - "max_disk_probes": 4, - "missing_worker_ms": 120000, - "tablets_per_core": 2 - }, - "allOf": [ - { - "$ref": "#/definitions/TabletBalancingConfig" - } - ] - }, - "bulk_read_bytes_per_sec": { - "description": "Bytes per second that bulk runs may read across every tablet of this process, with a burst of a quarter second (at least 4 MiB). Bulk runs wait for their bytes; point reads never wait. Unset or 0 leaves bulk runs unpaced.", - "type": [ - "integer", - "null" - ], - "format": "uint64", + "max_conflict_window_bytes": { + "default": 4194304, + "type": "integer", + "format": "uint", "minimum": 0.0 }, - "bulk_read_cache_blocks": { - "description": "Whether SST blocks a bulk run fetches enter the shared block cache. Defaults to true; false keeps large scans from evicting other volumes' hot blocks.", - "type": [ - "boolean", - "null" - ] + "max_memory_bytes": { + "default": 67108864, + "type": "integer", + "format": "uint", + "minimum": 0.0 }, - "bulk_read_fetch_tasks": { - "description": "Concurrent SST block fetches inside one bulk run's scan. Defaults to 1; 0 is treated as 1.", - "type": [ - "integer", - "null" - ], + "max_operation_bytes": { + "default": 8388608, + "type": "integer", "format": "uint", "minimum": 0.0 }, - "bulk_read_min_chunks": { - "description": "Chunk runs of at least this many chunks (4 KiB each) are read with the bulk scan settings below, as a table scan's read-ahead windows are. Unset or 0 reads every run with the normal settings.", - "type": [ - "integer", - "null" - ], + "max_pending_commits": { + "default": 128, + "type": "integer", "format": "uint", "minimum": 0.0 }, - "checkpoints": { - "default": { - "max_named_checkpoints_per_volume": 64, - "retention": null - }, - "allOf": [ - { - "$ref": "#/definitions/CheckpointConfig" - } - ] + "max_process_cache_bytes": { + "description": "Bytes all filesystem row caches in one process may retain together.", + "default": 1073741824, + "type": "integer", + "format": "uint", + "minimum": 0.0 }, - "cold_store": { - "default": { - "block_cache_bytes": null, - "compacted_sst_bytes": null, - "disk_cache_bytes": null, - "disk_cache_directory": null, - "disk_cache_on_compaction": null, - "disk_cache_on_flush": null, - "disk_cache_part_bytes": null, - "l0_max_ssts": null, - "max_concurrent_compactions": null, - "meta_cache_bytes": null, - "unflushed_budget_bytes": null - }, - "allOf": [ - { - "$ref": "#/definitions/ColdStoreConfig" - } - ] + "max_snapshot_age_ms": { + "default": 30000, + "type": "integer", + "format": "uint64", + "minimum": 0.0 }, - "cold_store_compression": { - "description": "Codec for SlateDB SST blocks in the cold store; defaults to `lz4`. Each SST records its own codec, so changing it keeps existing SSTs readable.", - "anyOf": [ - { - "$ref": "#/definitions/ColdStoreCompression" - }, - { - "type": "null" - } - ] + "max_snapshots": { + "default": 128, + "type": "integer", + "format": "uint", + "minimum": 0.0 }, - "command_timeout_ms": { - "description": "Floor for every typed Depot command deadline, in milliseconds. Each command keeps its own default (5 seconds generic, 30 seconds for actor storage); when set, the larger of the two bounds both the client's retry budget and the maintainer's handler timeout. Unset keeps the per-command defaults.", - "type": [ - "integer", - "null" - ], + "max_transaction_age_ms": { + "default": 300000, + "type": "integer", "format": "uint64", "minimum": 0.0 }, - "coordinator_request_capacity": { - "description": "Exact coordinator subject capacity. Defaults to 256.", - "type": [ - "integer", - "null" - ], + "max_transaction_bytes": { + "description": "Maximum application bytes in one filesystem transaction.", + "default": 134217728, + "type": "integer", "format": "uint", "minimum": 0.0 }, - "durable_max_events_per_commit": { - "description": "Most events of one durable state machine applied in one commit. Events that arrive while a commit is in flight are grouped up to this bound. Defaults to 16.", - "type": [ - "integer", - "null" - ], - "format": "uint32", + "max_unapplied_bytes": { + "description": "Most payload bytes one opening may have admitted ahead of the newest position its partition's maintainer reported applied. A new write past it is refused with a retry hint before it is built, so a writer faster than the apply, as under a slow cold store or compaction, waits at admission instead of growing an unbounded backlog.", + "default": 268435456, + "type": "integer", + "format": "uint", "minimum": 0.0 }, - "endpoint_cache_capacity": { - "description": "Maximum cached endpoint hints, including missing workers. Defaults to 4096.", - "default": null, - "type": [ - "integer", - "null" - ], + "max_value_bytes": { + "default": 1048576, + "type": "integer", "format": "uint", "minimum": 0.0 }, - "filesystem": { - "default": { - "max_cache_bytes": 8388608, - "max_conflict_window_bytes": 4194304, - "max_memory_bytes": 67108864, - "max_operation_bytes": 8388608, - "max_pending_commits": 128, - "max_process_cache_bytes": 1073741824, - "max_snapshot_age_ms": 30000, - "max_snapshots": 128, - "max_transaction_age_ms": 300000, - "max_transaction_bytes": 134217728, - "max_unapplied_bytes": 268435456, - "max_value_bytes": 1048576, - "note_ttl_ms": 1000, - "request_timeout_ms": 30000 - }, - "allOf": [ + "note_ttl_ms": { + "description": "How long a write's overlay notes (\"this page is at this sequence\") outlive the write before the filesystem drops them and keeps their rows only as cache. A later miss on one of those rows reads it from the maintainer once it has applied the write. About ten times the usual apply latency.", + "default": 1000, + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "request_timeout_ms": { + "default": 30000, + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "ForkConfig": { + "description": "Global bounds for source hold cleanup and background cross-region copies.", + "type": "object", + "properties": { + "check_grace_ms": { + "description": "Minimum age before an unfinished fork's destination is checked.", + "default": 60000, + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "materialize_batch_chunks": { + "description": "Further bounded by the maintainer's row and byte budgets.", + "default": 1024, + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "max_concurrent_materializations": { + "default": 2, + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "GcsObjectStoreConfig": { + "description": "Google Cloud Storage; defaults to the adapter's application default credentials.", + "type": "object", + "required": [ + "bucket" + ], + "properties": { + "bucket": { + "type": "string" + }, + "prefix": { + "default": null, + "type": [ + "string", + "null" + ] + }, + "service_account_key": { + "description": "Optional JSON service account credential override.", + "default": null, + "anyOf": [ { - "$ref": "#/definitions/FilesystemConfig" + "$ref": "#/definitions/Secret" + }, + { + "type": "null" } ] - }, - "flush_piggyback_min_bytes": { - "description": "Unflushed applied bytes at which a volume joins a tablet flush another volume requested. Defaults to 16 KiB.", + } + }, + "additionalProperties": false + }, + "Guard": { + "type": "object", + "properties": { + "host": { + "description": "Host for HTTP traffic", "type": [ - "integer", + "string", "null" ], - "format": "uint64", - "minimum": 0.0 + "format": "ip" }, - "flush_stage_concurrency": { - "description": "Volume records whose old rows one tablet filesystem flush reads at once while it stages. Staging excludes every other store operation of the tablet. Defaults to 16.", + "port": { + "description": "Port for HTTP traffic", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint16", "minimum": 0.0 }, - "forks": { - "default": { - "check_grace_ms": 60000, - "materialize_batch_chunks": 1024, - "max_concurrent_materializations": 2 - }, - "allOf": [ - { - "$ref": "#/definitions/ForkConfig" - } - ] - }, - "heartbeat_gc": { - "description": "Background heartbeat reclamation; separate from membership lease expiration.", - "default": { - "batch_interval_ms": null, - "batch_size": null, - "batch_timeout_ms": null, - "delete_concurrency": null, - "pass_interval_ms": null, - "retention_ms": null - }, - "allOf": [ - { - "$ref": "#/definitions/HeartbeatGcConfig" - } - ] - }, - "idle_unload_after_ms": { + "route_auth_check_timeout_ms": { + "description": "Timeout for guard-owned route authorization checks in milliseconds.", "type": [ "integer", "null" @@ -887,28 +821,8 @@ "format": "uint64", "minimum": 0.0 }, - "kv_commands": { - "default": { - "evicted_idle_warn_ms": null, - "max_command_bytes": null, - "max_eviction_closes": null, - "max_inflight_command_bytes": null, - "max_inflight_commands": null, - "max_open_volumes": null, - "max_worker_open_volume_bytes": null, - "max_worker_open_volumes": null, - "request_capacity": null, - "short_idle_close_ms": null, - "volume_idle_close_ms": null - }, - "allOf": [ - { - "$ref": "#/definitions/KvCommandConfig" - } - ] - }, - "learning_deadline_ms": { - "description": "How long a tablet replica-set change may stay in Learning before the coordinator aborts it and the tablet returns to its old members. Defaults to one hour and must be at least 45 minutes. It counts from the phase's start, not from the learner's progress, so it must outlast the membership holder wait (15 minutes) plus the copy of the largest log suffix a learner may have to catch up.", + "route_compute_timeout_ms": { + "description": "Timeout for resolving compute routes in milliseconds.", "type": [ "integer", "null" @@ -916,113 +830,99 @@ "format": "uint64", "minimum": 0.0 }, - "log_client_inflight_per_worker": { - "description": "Log shard requests a client keeps in flight to one storage worker. Later requests queue and go out together as one batch when a slot frees. Defaults to 2.", + "route_pegboard_auth_check_timeout_ms": { + "description": "Timeout for pegboard actor route authorization checks in milliseconds.", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "log_directory": { - "description": "Existing directory owned by one storage process. Required when storage services start.", + "tcp_nodelay": { + "description": "Enables TCP_NODELAY on accepted Guard sockets. Defaults to true.\n\nGuard carries actor nodes' WebSockets and client WebSocket and HTTP traffic, where most writes are small frames. With Nagle's algorithm on, a small frame waits for the peer to acknowledge the previous one, and a peer that delays its ACK holds it for about 40 ms. That delay landed on every actor's first response.", "type": [ - "string", + "boolean", "null" ] }, - "log_request_capacity": { - "description": "Exact replica subject capacity, shared by local clients and the shard. Defaults to 2048.", + "websocket_keepalive_interval_ms": { + "description": "Interval in milliseconds at which Guard sends a ping frame on every client WebSocket. Keeps idle connections alive through proxies that close quiet WebSockets, such as Cloudflare's roughly 100 second idle timeout. Must be greater than 0. Defaults to 30000 ms.", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 - }, - "log_shard": { - "description": "Optional overrides for the shard's disk, memory and operation bounds.", - "default": { - "checkpoint_bytes": null, - "checkpoint_timeout_ms": null, - "disk_read_concurrency": null, - "inbox_capacity": null, - "manifest_refresh_timeout_ms": null, - "max_admission_wait_ms": null, - "max_append_admission_wait_ms": null, - "max_batch_bytes": null, - "max_disk_bytes": null, - "max_disk_reads": null, - "max_loaded_volume_bytes": null, - "max_loaded_volumes": null, - "max_memory_bytes": null, - "max_memory_requests": null, - "max_retained_payload_bytes": null, - "max_retained_payload_bytes_per_volume": null, - "max_write_bytes": null, - "overload_retry_after_ms": null, - "preallocate_segments": null, - "recovery_timeout_ms": null, - "release_idle_payloads_after_ms": null, - "remove_segments_timeout_ms": null, - "segment_bytes": null, - "write_to_cold_at_disk_percent": null, - "write_to_disk_timeout_ms": null - }, - "allOf": [ - { - "$ref": "#/definitions/LogShardConfig" - } + } + }, + "additionalProperties": false + }, + "HardwareMetrics": { + "description": "Configuration for host hardware metrics.", + "type": "object", + "properties": { + "disk_probe": { + "description": "Times sequential writes and fsyncs on each data directory once at startup, in the background. Defaults to true.", + "type": [ + "boolean", + "null" ] }, - "lookup_request_capacity": { - "description": "Concurrent topology endpoint lookups and heartbeat inspections admitted per process. Defaults to 128.", + "disk_probe_bytes": { + "description": "Bytes the probe writes sequentially to each data directory. The fsync phase writes a further 400 KiB. Defaults to 64 MiB; at most 1 GiB.", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 - }, - "maintainer_inbox_capacity": { - "description": "Queued events one tablet maintainer accepts before it rejects new requests as overloaded. Every volume open, read, apply and status notice for the tablet passes through it, so a burst of actor starts on one tablet needs room for several events per start. Must be positive. Defaults to 4096.", + } + }, + "additionalProperties": false + }, + "HeartbeatGcConfig": { + "description": "Optional overrides for topology's bounded heartbeat cleanup service, which runs under the storage owner's singleton election. Topology defines the resolved defaults.", + "type": "object", + "properties": { + "batch_interval_ms": { + "description": "Pause between the batches of one pass. Defaults to 10 seconds.", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint64", "minimum": 0.0 }, - "maintainer_max_loaded_volumes": { - "description": "Volumes one tablet maintainer holds loaded at once, before opens of more are refused as overloaded. A loaded volume costs about 1.8 KiB of maintainer heap, so the default of 500,000 holds under 1 GiB per tablet. Must be positive.", + "batch_size": { + "description": "LIST entries examined per batch, 1 to 1000. Defaults to 128.", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint", "minimum": 0.0 }, - "maintainer_max_queued_opens": { - "description": "Volume opens queued in one tablet maintainer's inbox, not yet taken by its runner, at which a new open is refused as overloaded at once instead of joining the inbox. Other inbox events do not count. Opens queued past this would mostly expire before admission. Must be positive. Defaults to 1024.", + "batch_timeout_ms": { + "description": "Time budget of one batch. Defaults to 2 seconds.", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint64", "minimum": 0.0 }, - "maintainer_max_requests": { - "description": "Client requests one tablet maintainer tracks at once before it rejects more as overloaded. Must be positive. Defaults to 1024.", + "delete_concurrency": { + "description": "Conditional deletes in flight per batch, 1 to `batch_size`. Defaults to 4.", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint", "minimum": 0.0 }, - "manifest_refresh_ms": { - "description": "Fallback interval for re-reading the tablet manifest. Routing misses and `NotMaintainer` replies refresh it at once. Defaults to 30 seconds.", + "pass_interval_ms": { + "description": "Time between the starts of consecutive passes over both heartbeat prefixes. Defaults to one hour.", "type": [ "integer", "null" @@ -1030,44 +930,61 @@ "format": "uint64", "minimum": 0.0 }, - "max_background_cold_reads": { - "description": "Size of each background cold-read window per tablet maintainer: held-image source reads for forks, replica log reads for applies, fork jobs and fork cleanup jobs are each bounded by it separately, so they never take client read slots. Defaults to 4.", + "retention_ms": { + "description": "Defaults to 24 hours; clean shutdown markers remain available during this window.", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint64", "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "Jwt": { + "type": "object", + "properties": { + "audience": { + "type": [ + "string", + "null" + ] }, - "max_cold_reads": { - "description": "Client cold-store reads in flight per tablet maintainer: session opens, lifecycle row lookups and session reads share this window. A cold wake's reads fan out through it, so a narrow window serializes them. Object storage throughput scales almost linearly to about 32 parallel GETs, and a read slot is not always a GET, so 64 keeps a cold wake's reads from waiting on slots; on the load cluster a fully cold wake took about 850 ms at 4, 430 ms at 64 and 390 ms at 512. Defaults to 64.", + "default_duration": { + "description": "Default access-token lifetime, in seconds.", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint64", "minimum": 0.0 }, - "max_cold_reads_per_volume": { - "description": "Client session reads of one volume a tablet maintainer admits while reads of other volumes wait, so one large scan cannot hold every client cold-read slot. Slots no other volume waits for still go to that volume. Unset or 0 admits client reads in arrival order.", + "enabled": { + "description": "Controls verification, issuance, and key maintenance. Defaults to true.", "type": [ - "integer", + "boolean", "null" - ], - "format": "uint32", - "minimum": 0.0 + ] }, - "max_read_sessions": { - "description": "Filesystem read sessions per tablet maintainer. A session lives while its volume is being read and ends after `read_session_idle_ms` without a read, so this bounds how many volumes a tablet serves reads for at once. Opens past it are refused as overloaded. A held session retains about 1.2 KiB of maintainer heap, so the default of 16,384 holds under 20 MiB per tablet. Must be positive.", + "issuance_enabled": { + "description": "Pauses only new token minting. Defaults to true while JWT is enabled.", + "type": [ + "boolean", + "null" + ] + }, + "issuer_generation": { + "description": "Monotonic topology fence. Increment when changing the derived issuer or signing leader.", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "membership_refresh_cooldown_ms": { - "description": "Minimum milliseconds between miss-triggered membership refresh attempts, including failures.", + "key_max_signing_lifetime": { + "description": "Fail-closed maximum signing lifetime, in seconds (fourteen days by default). Normal rotation is still at day seven; this deadline only prevents A from signing forever if rotation stalls.", "type": [ "integer", "null" @@ -1075,8 +992,8 @@ "format": "uint64", "minimum": 0.0 }, - "memtable_flush_throttle_ms": { - "description": "Throttle for memtable flushes that nobody urgently waits on: a pass that comes due waits up to this long, so passes that come due close together share one upload and one L0 SST. Defaults to ten seconds.", + "key_publish_lead": { + "description": "Time to publish a pending public key before activation, in seconds (ten minutes by default). It provides verifier propagation time and does not extend the active key's lifetime.", "type": [ "integer", "null" @@ -1084,8 +1001,8 @@ "format": "uint64", "minimum": 0.0 }, - "read_cursor_session_idle_ms": { - "description": "How long a session opened at the latest position stays registered after its last read, in milliseconds. An HTTP directory cursor resumes such a session between pages, and no client reopens it at its position, so a paging client keeps its cursor for this long between pages. Must be positive. Defaults to 30,000, the session lifetime.", + "key_rotation_interval": { + "description": "Normal active-key age at rotation, in seconds (seven days by default).", "type": [ "integer", "null" @@ -1093,8 +1010,8 @@ "format": "uint64", "minimum": 0.0 }, - "read_session_idle_ms": { - "description": "How long a read session stays registered after its last read, in milliseconds. Each read extends it up to the session's lifetime, and a client reopens an ended session on its next read, so sessions track volumes being read rather than volumes open. Must be positive. Defaults to 2,000.", + "max_duration": { + "description": "Maximum access-token lifetime, in seconds. V1 is capped at one day.", "type": [ "integer", "null" @@ -1102,8 +1019,7 @@ "format": "uint64", "minimum": 0.0 }, - "simulated_fs_read_cost_us": { - "description": "Simulation only: runner time each filesystem read request costs a tablet maintainer, in microseconds, spent on the simulated clock so a maintainer busy with reads queues them as a loaded one does. Unset in deployments, where real processing time passes on its own.", + "unknown_kid_refresh_cooldown": { "type": [ "integer", "null" @@ -1111,8 +1027,7 @@ "format": "uint64", "minimum": 0.0 }, - "stop_poll_ms": { - "description": "Stop-permit retry interval. Defaults to one second.", + "verifier_cache_ttl": { "type": [ "integer", "null" @@ -1120,17 +1035,23 @@ "format": "uint64", "minimum": 0.0 }, - "stop_teardown_ms": { - "description": "Teardown budget after a stop permit or timeout. Defaults to one minute.", + "verifier_max_stale": { "type": [ "integer", "null" ], "format": "uint64", "minimum": 0.0 - }, - "stop_timeout_ms": { - "description": "Maximum coordinated stop wait from the first signal. Defaults to 30 minutes.", + } + }, + "additionalProperties": false + }, + "KvCommandConfig": { + "description": "Optional limits for typed commands and maintainer-owned filesystems.", + "type": "object", + "properties": { + "evicted_idle_warn_ms": { + "description": "Warns on eviction below this idle time; defaults to 15 seconds.", "type": [ "integer", "null" @@ -1138,44 +1059,43 @@ "format": "uint64", "minimum": 0.0 }, - "store_admission_scan_limit": { - "description": "Queued store items one admission pass looks at past work that cannot start yet. Work beyond it waits for the next pass. Must be positive. Defaults to 1024.", + "max_command_bytes": { "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint", "minimum": 0.0 }, - "store_max_flush_staging": { - "description": "Tablet filesystem flushes one tablet maintainer lets stage at once. Staging writes the flush's records into the store. Must be positive. Defaults to 1.", + "max_eviction_closes": { + "description": "Idle KV command volumes one partition's host closes at once to make room past its cap or the worker's budget. Each open refused at a full cap starts one such close, so a burst admits at this many closes per close latency. A closing volume keeps its memory charge until its close finishes. Defaults to 32.", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint", "minimum": 0.0 }, - "store_max_flush_uploads": { - "description": "Tablet filesystem flushes one tablet maintainer keeps in flight at once, staging or uploading; a staging flush counts because it uploads next. Must be at least `store_max_flush_staging`. Defaults to 2.", + "max_inflight_command_bytes": { + "description": "Received bytes of the KV commands one partition's host has admitted and not finished. A command that would exceed it is refused at once as unavailable, which callers retry within their deadline. Must hold at least one command of `max_command_bytes`. Defaults to 64 MiB, so a worker maintaining four partitions holds at most 256 MiB of command payloads.", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint", "minimum": 0.0 }, - "store_max_keyed_in_flight": { - "description": "Filesystem applies and loads one tablet maintainer admits to its store at once. They run concurrently, one task each, and their replica reads stay bounded by the cold byte budget, so the cap sizes concurrency for a burst of volume creates rather than memory. Must be positive. Defaults to 256.", + "max_inflight_commands": { + "description": "Maximum simultaneous handlers per registered command class.", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint", "minimum": 0.0 }, - "store_volume_lock_stripes": { - "description": "Volume lock stripes of each tablet filesystem store. Two volumes on one stripe serialize their store work. Must be positive. Defaults to 1024.", + "max_open_volumes": { + "description": "KV command volumes one partition's host holds open at once, closing ones included. Defaults to the worker-wide cap, so by default only the worker's memory budget limits a partition.", "type": [ "integer", "null" @@ -1183,35 +1103,17 @@ "format": "uint", "minimum": 0.0 }, - "store_volume_locks": { - "description": "Which store work takes volume stripes. `core` (the default) trusts the maintainer core to order applies, loads, session opens, lifecycle lookups and the flush retention publish, so they take only the tablet lock; stripes then guard only checkpoint-session opens against hold releases, checkpoint deletions and sweeps. `stripes` keeps a stripe on every operation, as before.", - "anyOf": [ - { - "$ref": "#/definitions/StoreVolumeLocks" - }, - { - "type": "null" - } - ] - }, - "volume_client": { - "default": { - "close_after_idle_ms": null, - "max_loaded_volumes": null, - "max_requests": null, - "max_volume_key_bytes": null, - "open_timeout_ms": null, - "payload_codec": null, - "sweep_interval_ms": null - }, - "allOf": [ - { - "$ref": "#/definitions/VolumeClientConfig" - } - ] + "max_worker_open_volume_bytes": { + "description": "Memory, in bytes, that the KV command volumes of this worker may hold together across every partition it maintains, closing ones included. Each open volume is charged 80 KiB, its measured fixed cost with allocator headroom: its host slot, volume client and filesystem owner, plus the log replicas and maintainer state its open loads. Caches and command payloads are bounded separately. One worker-wide budget bounds memory however many partitions the worker holds, and a create burst opens one volume per new key, so the default of 5 GiB holds 65,536 volumes (default 5 GiB).", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 }, - "volume_request_capacity": { - "description": "Per-subject lifecycle request capacity, isolated from other UPS traffic. Defaults to 1024.", + "max_worker_open_volumes": { + "description": "A count backstop to `max_worker_open_volume_bytes`; unset by default, so the byte budget alone sets the worker's cap.", "type": [ "integer", "null" @@ -1219,17 +1121,17 @@ "format": "uint", "minimum": 0.0 }, - "volume_request_timeout_ms": { - "description": "Entire lifecycle RPC budget, including route refreshes. Defaults to five seconds.", + "request_capacity": { + "description": "KV commands one worker holds received and unanswered, and that one caller may have outstanding to one worker, isolated from volume lifecycle requests. A full window refuses a command at once as overloaded, and the caller retries it within its deadline. Each partition's host admits at most the sum of its commands' concurrency caps (4,608 with the default caps and the engine's commands), so the default of 32,768 lets those caps, not this window, refuse load first on a worker that maintains up to seven partitions. Defaults to 32,768.", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint", "minimum": 0.0 }, - "write_to_cold_above_bytes": { - "description": "Committed suffix threshold, default 64 MiB and maximum 256 MiB.", + "short_idle_close_ms": { + "description": "Idle close for volumes of short-lived commands, such as one Epoxy key per volume. Closing also begins the volume's unload. Defaults to 2 seconds.", "type": [ "integer", "null" @@ -1237,8 +1139,8 @@ "format": "uint64", "minimum": 0.0 }, - "write_to_cold_after_ms": { - "description": "Cold-write age from the first unflushed entry, plus up to a tenth of it as jitter. Defaults to one minute. Storage workers require the age with its jitter to stay below `stop_timeout_ms`, so a stopping worker never waits on a slower tiering cadence than its own stop budget.", + "volume_idle_close_ms": { + "description": "Defaults to 60 seconds.", "type": [ "integer", "null" @@ -1249,206 +1151,79 @@ }, "additionalProperties": false }, - "Epoxy": { - "description": "Epoxy runs in a single datacenter with fixed membership, so it has no settings yet. The section stays so multi-region settings have a home.", - "type": "object", - "additionalProperties": false - }, - "FileSystemObjectStoreConfig": { - "description": "A local directory used by one engine process at a time. Conditional writes are atomic only among requests of that process.", - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "description": "Created when it does not exist.", - "type": "string" - } - }, - "additionalProperties": false - }, - "FilesystemConfig": { + "LogShardConfig": { + "description": "The log shard owns resolved defaults and validates relationships between these limits.", "type": "object", "properties": { - "max_cache_bytes": { - "description": "Bytes one filesystem's row cache may retain, a fairness ceiling inside `max_process_cache_bytes`.", - "default": 8388608, - "type": "integer", - "format": "uint", + "checkpoint_bytes": { + "type": [ + "integer", + "null" + ], + "format": "uint64", "minimum": 0.0 }, - "max_conflict_window_bytes": { - "default": 4194304, - "type": "integer", - "format": "uint", + "checkpoint_timeout_ms": { + "type": [ + "integer", + "null" + ], + "format": "uint64", "minimum": 0.0 }, - "max_memory_bytes": { - "default": 67108864, - "type": "integer", - "format": "uint", + "disk_read_concurrency": { + "description": "Disk reads executing at once beside the shard's write queue. Each holds one scan buffer of two maximum batches from `max_memory_bytes`. Defaults to 8.", + "type": [ + "integer", + "null" + ], + "format": "uint32", "minimum": 0.0 }, - "max_operation_bytes": { - "default": 8388608, - "type": "integer", + "inbox_capacity": { + "type": [ + "integer", + "null" + ], "format": "uint", "minimum": 0.0 }, - "max_pending_commits": { - "default": 128, - "type": "integer", - "format": "uint", + "manifest_refresh_timeout_ms": { + "type": [ + "integer", + "null" + ], + "format": "uint64", "minimum": 0.0 }, - "max_process_cache_bytes": { - "description": "Bytes all filesystem row caches in one process may retain together.", - "default": 1073741824, - "type": "integer", - "format": "uint", + "max_admission_wait_ms": { + "description": "Longest wait, in milliseconds, of a request other than an append in the shard's inbox. A request that waited longer is refused as overloaded before any work, with a retry hint, so a saturated shard sheds load instead of queueing past the volume client's quorum timeout. Defaults to 1000.", + "type": [ + "integer", + "null" + ], + "format": "uint64", "minimum": 0.0 }, - "max_snapshot_age_ms": { - "default": 30000, - "type": "integer", + "max_append_admission_wait_ms": { + "description": "The same bound for appends, commit announcements, trims and forgets, which carry writes a volume client already admitted or free memory and disk, so opens and other new work are shed first. At least `max_admission_wait_ms` and just under the volume client's 2 s append timeout, past which the client has resent the append anyway. Defaults to 1800.", + "type": [ + "integer", + "null" + ], "format": "uint64", "minimum": 0.0 }, - "max_snapshots": { - "default": 128, - "type": "integer", - "format": "uint", + "max_batch_bytes": { + "type": [ + "integer", + "null" + ], + "format": "uint32", "minimum": 0.0 }, - "max_transaction_age_ms": { - "default": 300000, - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "max_transaction_bytes": { - "description": "Maximum application bytes in one filesystem transaction.", - "default": 134217728, - "type": "integer", - "format": "uint", - "minimum": 0.0 - }, - "max_unapplied_bytes": { - "description": "Most payload bytes one opening may have admitted ahead of the newest position its tablet's maintainer reported applied. A new write past it is refused with a retry hint before it is built, so a writer faster than the apply, as under a slow cold store or compaction, waits at admission instead of growing an unbounded backlog.", - "default": 268435456, - "type": "integer", - "format": "uint", - "minimum": 0.0 - }, - "max_value_bytes": { - "default": 1048576, - "type": "integer", - "format": "uint", - "minimum": 0.0 - }, - "note_ttl_ms": { - "description": "How long a write's overlay notes (\"this page is at this sequence\") outlive the write before the filesystem drops them and keeps their rows only as cache. A later miss on one of those rows reads it from the maintainer once it has applied the write. About ten times the usual apply latency.", - "default": 1000, - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "request_timeout_ms": { - "default": 30000, - "type": "integer", - "format": "uint64", - "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "ForkConfig": { - "description": "Global bounds for source hold cleanup and background cross-region copies.", - "type": "object", - "properties": { - "check_grace_ms": { - "description": "Minimum age before an unfinished fork's destination is checked.", - "default": 60000, - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "materialize_batch_chunks": { - "description": "Further bounded by the maintainer's row and byte budgets.", - "default": 1024, - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "max_concurrent_materializations": { - "default": 2, - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "GcsObjectStoreConfig": { - "description": "Google Cloud Storage; defaults to the adapter's application default credentials.", - "type": "object", - "required": [ - "bucket" - ], - "properties": { - "bucket": { - "type": "string" - }, - "prefix": { - "default": null, - "type": [ - "string", - "null" - ] - }, - "service_account_key": { - "description": "Optional JSON service account credential override.", - "default": null, - "anyOf": [ - { - "$ref": "#/definitions/Secret" - }, - { - "type": "null" - } - ] - } - }, - "additionalProperties": false - }, - "Guard": { - "type": "object", - "properties": { - "disable_gateway_auth": { - "description": "TODO: Remove eventually and reenable gateway auth permanently. See RVTEE-672.", - "default": false, - "type": "boolean" - }, - "host": { - "description": "Host for HTTP traffic", - "type": [ - "string", - "null" - ], - "format": "ip" - }, - "port": { - "description": "Port for HTTP traffic", - "type": [ - "integer", - "null" - ], - "format": "uint16", - "minimum": 0.0 - }, - "route_auth_check_timeout_ms": { - "description": "Timeout for guard-owned route authorization checks in milliseconds.", + "max_disk_bytes": { + "description": "Disk bytes the shard's log may hold. When unset, a storage worker sizes it from the free space of its filesystem at startup, shared with the cold-store disk cache.", "type": [ "integer", "null" @@ -1456,17 +1231,17 @@ "format": "uint64", "minimum": 0.0 }, - "route_compute_timeout_ms": { - "description": "Timeout for resolving compute routes in milliseconds.", + "max_disk_reads": { + "description": "Most reads waiting on the shard's disk at once; a read that needs disk beyond it is rejected as overloaded and retried by the caller. Defaults to 256.", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint32", "minimum": 0.0 }, - "route_pegboard_auth_check_timeout_ms": { - "description": "Timeout for pegboard actor route authorization checks in milliseconds.", + "max_loaded_volume_bytes": { + "description": "Memory, in bytes, that one log shard's loaded replicas may hold, charged at 1.5 KiB per replica, the measured heap of a quiet loaded replica with headroom. A load past it is refused as `too_many_loaded_volumes`, a typed refusal its open retries. The default of 1.5 GiB holds 1,048,576 replicas (default 1.5 GiB).", "type": [ "integer", "null" @@ -1474,45 +1249,16 @@ "format": "uint64", "minimum": 0.0 }, - "tcp_nodelay": { - "description": "Enables TCP_NODELAY on accepted Guard sockets. Defaults to true.\n\nGuard carries actor runners' Envoy WebSockets and client WebSocket and HTTP traffic, where most writes are small frames. With Nagle's algorithm on, a small frame waits for the peer to acknowledge the previous one, and a peer that delays its ACK holds it for about 40 ms. That delay landed on every actor's first response.", - "type": [ - "boolean", - "null" - ] - } - }, - "additionalProperties": false - }, - "HardwareMetrics": { - "description": "Configuration for host hardware metrics.", - "type": "object", - "properties": { - "disk_probe": { - "description": "Times sequential writes and fsyncs on each data directory once at startup, in the background. Defaults to true.", - "type": [ - "boolean", - "null" - ] - }, - "disk_probe_bytes": { - "description": "Bytes the probe writes sequentially to each data directory. The fsync phase writes a further 400 KiB. Defaults to 64 MiB; at most 1 GiB.", + "max_loaded_volumes": { + "description": "A count backstop to `max_loaded_volume_bytes`; unset by default, so the byte budget alone sets the shard's replica cap.", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint32", "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "HeartbeatGcConfig": { - "description": "Optional overrides for topology's bounded heartbeat cleanup service, which runs under the storage owner's singleton election. Topology defines the resolved defaults.", - "type": "object", - "properties": { - "batch_interval_ms": { - "description": "Pause between the batches of one pass. Defaults to 10 seconds.", + }, + "max_memory_bytes": { "type": [ "integer", "null" @@ -1520,17 +1266,16 @@ "format": "uint64", "minimum": 0.0 }, - "batch_size": { - "description": "LIST entries examined per batch, 1 to 1000. Defaults to 128.", + "max_memory_requests": { "type": [ "integer", "null" ], - "format": "uint", + "format": "uint32", "minimum": 0.0 }, - "batch_timeout_ms": { - "description": "Time budget of one batch. Defaults to 2 seconds.", + "max_retained_payload_bytes": { + "description": "Encoded bytes of synced log entry payloads the shard keeps in memory for reads; defaults to a sixteenth of `max_memory_bytes`. Older payloads are read from disk.", "type": [ "integer", "null" @@ -1538,17 +1283,8 @@ "format": "uint64", "minimum": 0.0 }, - "delete_concurrency": { - "description": "Conditional deletes in flight per batch, 1 to `batch_size`. Defaults to 4.", - "type": [ - "integer", - "null" - ], - "format": "uint", - "minimum": 0.0 - }, - "pass_interval_ms": { - "description": "Time between the starts of consecutive passes over both heartbeat prefixes. Defaults to one hour.", + "max_retained_payload_bytes_per_volume": { + "description": "Synced payload bytes one volume replica keeps after each disk write; defaults to 32 KiB.", "type": [ "integer", "null" @@ -1556,29 +1292,16 @@ "format": "uint64", "minimum": 0.0 }, - "retention_ms": { - "description": "Defaults to 24 hours; clean shutdown markers remain available during this window.", + "max_write_bytes": { "type": [ "integer", "null" ], "format": "uint64", "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "Jwt": { - "type": "object", - "properties": { - "audience": { - "type": [ - "string", - "null" - ] }, - "default_duration": { - "description": "Default access-token lifetime, in seconds.", + "overload_retry_after_ms": { + "description": "Retry hint, in milliseconds, on a request refused because the inbox or a request budget is full. Defaults to 100.", "type": [ "integer", "null" @@ -1586,31 +1309,15 @@ "format": "uint64", "minimum": 0.0 }, - "enabled": { - "description": "Controls verification, issuance, and key maintenance. Defaults to true.", - "type": [ - "boolean", - "null" - ] - }, - "issuance_enabled": { - "description": "Pauses only new token minting. Defaults to true while JWT is enabled.", + "preallocate_segments": { + "description": "Writes log segments into files zero-filled to `segment_bytes` ahead of use, so each commit overwrites allocated blocks and syncs only its data instead of journaling a file size change. On the load cluster's disks this halves the sync and commit latency. The unused allocation of the active segment and one spare segment count toward `max_disk_bytes`. Each write also records, in a header slot synced with it, how far earlier syncs reached, so a disk that returns synced pages as zeros is reported as corruption rather than read as free space. Needs `segment_bytes` above 8 KiB. Defaults to true.", "type": [ "boolean", "null" ] }, - "issuer_generation": { - "description": "Monotonic topology fence. Increment when changing the derived issuer or signing leader.", - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0.0 - }, - "key_max_signing_lifetime": { - "description": "Fail-closed maximum signing lifetime, in seconds (fourteen days by default). Normal rotation is still at day seven; this deadline only prevents A from signing forever if rotation stalls.", + "recovery_timeout_ms": { + "description": "How long log shard recovery may go without finishing another file before the shard fails (default 120 s). It does not bound the whole scan, which grows with the log.", "type": [ "integer", "null" @@ -1618,8 +1325,8 @@ "format": "uint64", "minimum": 0.0 }, - "key_publish_lead": { - "description": "Time to publish a pending public key before activation, in seconds (ten minutes by default). It provides verifier propagation time and does not extend the active key's lifetime.", + "release_idle_payloads_after_ms": { + "description": "How long a volume replica appends nothing before its synced payloads leave memory; defaults to 5000.", "type": [ "integer", "null" @@ -1627,8 +1334,7 @@ "format": "uint64", "minimum": 0.0 }, - "key_rotation_interval": { - "description": "Normal active-key age at rotation, in seconds (seven days by default).", + "remove_segments_timeout_ms": { "type": [ "integer", "null" @@ -1636,8 +1342,7 @@ "format": "uint64", "minimum": 0.0 }, - "max_duration": { - "description": "Maximum access-token lifetime, in seconds. V1 is capped at one day.", + "segment_bytes": { "type": [ "integer", "null" @@ -1645,92 +1350,146 @@ "format": "uint64", "minimum": 0.0 }, - "unknown_kid_refresh_cooldown": { + "write_to_cold_at_disk_percent": { + "description": "Early cold-write watermark, 1..99 percent of the disk cap; defaults to 75.", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint8", "minimum": 0.0 }, - "verifier_cache_ttl": { + "write_to_disk_timeout_ms": { "type": [ "integer", "null" ], "format": "uint64", "minimum": 0.0 - }, - "verifier_max_stale": { + } + }, + "additionalProperties": false + }, + "Logs": { + "type": "object", + "properties": { + "redirect_logs_dir": { + "default": null, "type": [ - "integer", + "string", "null" - ], - "format": "uint64", - "minimum": 0.0 + ] } }, "additionalProperties": false }, - "KvCommandConfig": { - "description": "Optional limits for typed commands and maintainer-owned filesystems.", + "Metrics": { + "description": "Configuration for the metrics service.", "type": "object", "properties": { - "evicted_idle_warn_ms": { - "description": "Warns on eviction below this idle time; defaults to 15 seconds.", + "hardware": { + "description": "Host hardware metrics, including a short disk probe of each data directory at startup.", + "default": { + "disk_probe": null, + "disk_probe_bytes": null + }, + "allOf": [ + { + "$ref": "#/definitions/HardwareMetrics" + } + ] + }, + "host": { "type": [ - "integer", + "string", "null" ], - "format": "uint64", - "minimum": 0.0 + "format": "ip" }, - "max_command_bytes": { + "port": { "type": [ "integer", "null" ], - "format": "uint", + "format": "uint16", "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "MigrateFromV2": { + "description": "Settings for moving one V2 namespace's actors into this cluster.\n\nThe section is read through `config.dynamic()`, and a dynamic config update replaces it as a whole. `migrate_seed` is the exception: it is fixed at startup, because a new seed reshuffles which actors fall under `migrate_ratio`, so raising the ratio would no longer only add actors.", + "type": "object", + "required": [ + "endpoint", + "namespace" + ], + "properties": { + "api_urls": { + "description": "V2's public API per datacenter label, which the migrator lists and moves actors through.", + "default": {}, + "type": "object", + "additionalProperties": { + "type": "string" + } }, - "max_eviction_closes": { - "description": "Idle KV command volumes one tablet's host closes at once to make room past its cap or the worker's budget. Each open refused at a full cap starts one such close, so a burst admits at this many closes per close latency. A closing volume keeps its memory charge until its close finishes. Defaults to 32.", + "confirm_delay_ms": { "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "max_inflight_command_bytes": { - "description": "Received bytes of the KV commands one tablet's host has admitted and not finished. A command that would exceed it is refused at once as unavailable, which callers retry within their deadline. Must hold at least one command of `max_command_bytes`. Defaults to 64 MiB, so a worker maintaining four tablets holds at most 256 MiB of command payloads.", + "create_ratio": { + "description": "Share of new creates that land in this cluster. Keyless creates draw against it; keyed creates move here only at 1.0.", + "default": 0.0, + "type": "number", + "format": "double" + }, + "endpoint": { + "description": "V2's public gateway, where requests for actors this cluster does not hold are proxied.", + "type": "string" + }, + "max_actors_per_sec": { "type": [ "integer", "null" ], - "format": "uint", + "format": "uint32", "minimum": 0.0 }, - "max_inflight_commands": { - "description": "Maximum simultaneous handlers per registered command class.", + "max_copy_bytes": { + "description": "Largest actor the migrator copies, by V2's reported SQLite size plus its KV estimate. Larger actors are skipped as `too_large` on every pass, so they never hold a slot; raise it once the rest of the namespace has moved to migrate them. Defaults to 10 GiB.", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "max_open_volumes": { - "description": "KV command volumes one tablet's host holds open at once, closing ones included. Defaults to the worker-wide cap, so by default only the worker's memory budget limits a tablet.", + "max_in_flight": { "type": [ "integer", "null" ], - "format": "uint", + "format": "uint32", "minimum": 0.0 }, - "max_worker_open_volume_bytes": { - "description": "Memory, in bytes, that the KV command volumes of this worker may hold together across every tablet it maintains, closing ones included. Each open volume is charged 80 KiB, its measured fixed cost with allocator headroom: its host slot, volume client and filesystem owner, plus the log replicas and maintainer state its open loads. Caches and command payloads are bounded separately. One worker-wide budget bounds memory however many tablets the worker holds, and a create burst opens one volume per new key, so the default of 5 GiB holds 65,536 volumes (default 5 GiB).", + "migrate_ratio": { + "description": "Share of existing V2 actors the migrator moves, picked by a stable hash of the actor id.", + "default": 0.0, + "type": "number", + "format": "double" + }, + "migrate_seed": { + "description": "Seed of the hash behind `migrate_ratio`.", + "default": 0, + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "min_sleep_ms": { "type": [ "integer", "null" @@ -1738,35 +1497,35 @@ "format": "uint64", "minimum": 0.0 }, - "max_worker_open_volumes": { - "description": "A count backstop to `max_worker_open_volume_bytes`; unset by default, so the byte budget alone sets the worker's cap.", + "namespace": { + "description": "The V2 namespace being migrated.", + "type": "string" + }, + "pass_interval_ms": { "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "request_capacity": { - "description": "KV commands one worker holds received and unanswered, and that one caller may have outstanding to one worker, isolated from volume lifecycle requests. A full window refuses a command at once as overloaded, and the caller retries it within its deadline. Each tablet's host admits at most the sum of its commands' concurrency caps (4,608 with the default caps and the engine's commands), so the default of 32,768 lets those caps, not this window, refuse load first on a worker that maintains up to seven tablets. Defaults to 32,768.", + "target_namespace": { + "description": "The namespace here that the actors land in. Defaults to the V2 namespace's name.", + "default": null, "type": [ - "integer", + "string", "null" - ], - "format": "uint", - "minimum": 0.0 + ] }, - "short_idle_close_ms": { - "description": "Idle close for volumes of short-lived commands, such as one Epoxy key per volume. Closing also begins the volume's unload. Defaults to 2 seconds.", + "token": { + "description": "The namespace-wide V2 token for V2's migration API and the public API calls routing makes. Never logged.", + "default": null, "type": [ - "integer", + "string", "null" - ], - "format": "uint64", - "minimum": 0.0 + ] }, - "volume_idle_close_ms": { - "description": "Defaults to 60 seconds.", + "wake_horizon_ms": { "type": [ "integer", "null" @@ -1777,11 +1536,20 @@ }, "additionalProperties": false }, - "LogShardConfig": { - "description": "The log shard owns resolved defaults and validates relationships between these limits.", + "ObjectStorageConfig": { "type": "object", "properties": { - "checkpoint_bytes": { + "primary": { + "default": "in_memory", + "allOf": [ + { + "$ref": "#/definitions/ObjectStoreBackend" + } + ] + }, + "read_first_attempt_ms": { + "description": "Milliseconds the first attempt of a small GET or HEAD may wait for response headers before the client cuts it off and retries it with its normal timeouts. A request on a stalled connection otherwise waits the full 30 s client timeout. Default 250, set from the load cluster's Azure account, where about 0.02% of small requests took longer; 0 disables it. Response bodies are never cut off.", + "default": null, "type": [ "integer", "null" @@ -1789,7 +1557,9 @@ "format": "uint64", "minimum": 0.0 }, - "checkpoint_timeout_ms": { + "write_first_attempt_bytes_per_second": { + "description": "The upload rate a conditional PUT's first attempt may fall to before it is cut off, which extends `write_first_attempt_ms` by the body's size. Default 8 MiB/s.", + "default": null, "type": [ "integer", "null" @@ -1797,288 +1567,367 @@ "format": "uint64", "minimum": 0.0 }, - "disk_read_concurrency": { - "description": "Disk reads executing at once beside the shard's write queue. Each holds one scan buffer of two maximum batches from `max_memory_bytes`. Defaults to 8.", + "write_first_attempt_ms": { + "description": "Milliseconds the first attempt of a small conditional PUT (a lease, heartbeat or manifest) may wait for response headers, before the upload time its body needs at `write_first_attempt_bytes_per_second`. Unset by default, which disables it. Healthy conditional PUT latency is calibrated only on Azure; a healthy GCS PUT can take over 250 ms. GCS also allows about one write per second to one object, so a retry shortly after a cut-off on the same lease or heartbeat object risks a 429, an unknown outcome and an extra readback. Set it only from measured conditional PUT latency of the backend.", + "default": null, "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint64", "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "ObjectStoreBackend": { + "oneOf": [ + { + "type": "string", + "enum": [ + "in_memory" + ] }, - "inbox_capacity": { + { + "description": "A local directory, for a single engine process that keeps its data across restarts.", + "type": "object", + "required": [ + "file_system" + ], + "properties": { + "file_system": { + "$ref": "#/definitions/FileSystemObjectStoreConfig" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "s3" + ], + "properties": { + "s3": { + "$ref": "#/definitions/S3ObjectStoreConfig" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "azure" + ], + "properties": { + "azure": { + "$ref": "#/definitions/AzureObjectStoreConfig" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "gcs" + ], + "properties": { + "gcs": { + "$ref": "#/definitions/GcsObjectStoreConfig" + } + }, + "additionalProperties": false + } + ] + }, + "Outbound": { + "description": "Policy for outbound HTTP requests to user-configured destinations, such as serverless node URLs.\n\nThese requests originate from inside the trusted engine network, so without restrictions a caller who can configure a node can reach internal-only services. The defaults deny every non-globally-routable destination except loopback.", + "type": "object", + "properties": { + "allow_cidrs": { + "description": "Additional CIDRs that are always permitted, evaluated after `deny_cidrs`.\n\nUse this to reach a specific internal service without opening up the whole private range.", "type": [ - "integer", + "array", "null" ], - "format": "uint", - "minimum": 0.0 + "items": { + "type": "string" + } }, - "manifest_refresh_timeout_ms": { + "allow_hosts": { + "description": "Hostnames that are always permitted, whatever they resolve to.\n\nMatched exactly and case-insensitively, with no wildcards. Use this for a first-party service whose address is not known ahead of time, such as a Kubernetes service name. Anything served at a listed host becomes reachable by every node config, so list individual hosts rather than a shared entry point.", "type": [ - "integer", + "array", "null" ], - "format": "uint64", - "minimum": 0.0 + "items": { + "type": "string" + } }, - "max_admission_wait_ms": { - "description": "Longest wait, in milliseconds, of a request other than an append in the shard's inbox. A request that waited longer is refused as overloaded before any work, with a retry hint, so a saturated shard sheds load instead of queueing past the volume client's quorum timeout. Defaults to 1000.", + "allow_insecure_scheme": { + "description": "Allow plaintext `http://` destinations. When disabled only `https://` is permitted.", "type": [ - "integer", + "boolean", "null" - ], - "format": "uint64", - "minimum": 0.0 + ] }, - "max_append_admission_wait_ms": { - "description": "The same bound for appends, commit announcements, trims and forgets, which carry writes a volume client already admitted or free memory and disk, so opens and other new work are shed first. At least `max_admission_wait_ms` and just under the volume client's 2 s append timeout, past which the client has resent the append anyway. Defaults to 1800.", + "allow_loopback": { + "description": "Allow destinations that resolve to loopback addresses (127.0.0.0/8, ::1).\n\nEnabled by default so local development against `http://localhost:...` works without configuration.", "type": [ - "integer", + "boolean", "null" - ], - "format": "uint64", - "minimum": 0.0 + ] }, - "max_batch_bytes": { + "allow_private_networks": { + "description": "Allow destinations that resolve to private, link-local, shared (CGNAT), or otherwise non-globally-routable addresses.\n\nSelf-hosted deployments that point nodes at addresses on their own network, such as a Docker Compose service name, need this enabled.", "type": [ - "integer", + "boolean", + "null" + ] + }, + "deny_cidrs": { + "description": "Additional CIDRs that are always denied. Takes precedence over every allow rule.", + "type": [ + "array", "null" ], - "format": "uint32", - "minimum": 0.0 + "items": { + "type": "string" + } }, - "max_disk_bytes": { - "description": "Disk bytes the shard's log may hold. When unset, a storage worker sizes it from the free space of its filesystem at startup, shared with the cold-store disk cache.", + "max_redirects": { + "description": "Maximum number of redirects to follow. Every hop is re-checked against this policy.", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "PartitionBalancingConfig": { + "description": "Static partition placement policy; membership and lease timings remain topology-owned.", + "type": "object", + "properties": { + "destination_stability_ms": { + "description": "How long a new worker must be listed in discovery, and pass one disk probe, before the coordinator places partitions on it. Must exceed the topology worker lease plus one renewal and the takeover grace, about 35 s, so a worker that crashes soon after it first appears has left discovery before it qualifies. Startup refuses a shorter value.", + "default": 60000, + "type": "integer", + "format": "uint64", "minimum": 0.0 }, - "max_disk_reads": { - "description": "Most reads waiting on the shard's disk at once; a read that needs disk beyond it is rejected as overloaded and retried by the caller. Defaults to 256.", - "type": [ - "integer", - "null" - ], + "enabled": { + "description": "Whether the partition coordinator places, splits and replaces partitions on its own. When disabled, the layout changes only through operator commands: a new cluster gets no first partition until an operator creates one, and a missing worker is never replaced.", + "default": true, + "type": "boolean" + }, + "max_disk_probes": { + "description": "Maximum concurrent disk admission requests made by the partition coordinator.", + "default": 4, + "type": "integer", "format": "uint32", "minimum": 0.0 }, - "max_loaded_volume_bytes": { - "description": "Memory, in bytes, that one log shard's loaded replicas may hold, charged at 1.5 KiB per replica, the measured heap of a quiet loaded replica with headroom. A load past it is refused as `too_many_loaded_volumes`, a typed refusal its open retries. The default of 1.5 GiB holds 1,048,576 replicas (default 1.5 GiB).", + "missing_worker_ms": { + "description": "How long an assigned worker must be missing from discovery before its replicas are replaced. Counted from when discovery drops it, which is itself one lease after its last renewal.", + "default": 120000, + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "partitions_per_core": { + "default": 2, + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "PeerTransport": { + "description": "Connections and flow-control windows per peer. Omitted values use the defaults.", + "type": "object", + "properties": { + "channel_large_request_bytes": { + "description": "Requests with a larger payload use a peer's large-request channels, so they never queue ahead of small requests on one stream (default 64 KiB).", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint", "minimum": 0.0 }, - "max_loaded_volumes": { - "description": "A count backstop to `max_loaded_volume_bytes`; unset by default, so the byte budget alone sets the shard's replica cap.", + "channel_max_write_bytes": { + "description": "Most bytes a peer channel writes at once from its queue (default 256 KiB).", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint", "minimum": 0.0 }, - "max_memory_bytes": { + "channel_queue_bytes": { + "description": "Bytes of requests a peer channel queues for writing; a request that would exceed it is refused, though an empty queue always takes one (default 64 MiB).", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint", "minimum": 0.0 }, - "max_memory_requests": { + "channel_queue_frames": { + "description": "Frames a peer channel queues for writing; a full queue refuses the request (default 8192).", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint", "minimum": 0.0 }, - "max_retained_payload_bytes": { - "description": "Encoded bytes of synced log entry payloads the shard keeps in memory for reads; defaults to a sixteenth of `max_memory_bytes`. Older payloads are read from disk.", + "channel_reply_queue_bytes": { + "description": "Bytes of replies one served peer channel queues for writing. A channel at its cap refuses new requests as overloaded until its caller reads or the queued replies expire (default 64 MiB).", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint", "minimum": 0.0 }, - "max_retained_payload_bytes_per_volume": { - "description": "Synced payload bytes one volume replica keeps after each disk write; defaults to 32 KiB.", + "incoming_channel_capacity": { + "description": "Peer channels this worker may serve across all remote workers (default 4096).", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint", "minimum": 0.0 }, - "max_write_bytes": { + "outgoing_channel_capacity": { + "description": "Peer channels this worker may open across all remote workers (default 4096).", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint", "minimum": 0.0 }, - "overload_retry_after_ms": { - "description": "Retry hint, in milliseconds, on a request refused because the inbox or a request budget is full. Defaults to 100.", + "reply_queue_bytes": { + "description": "Bytes of replies queued across every served peer channel of this worker. At the cap every channel refuses new requests as overloaded (default 1 GiB).", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint", "minimum": 0.0 }, - "preallocate_segments": { - "description": "Writes log segments into files zero-filled to `segment_bytes` ahead of use, so each commit overwrites allocated blocks and syncs only its data instead of journaling a file size change. On the load cluster's disks this halves the sync and commit latency. The unused allocation of the active segment and one spare segment count toward `max_disk_bytes`. Each write also records, in a header slot synced with it, how far earlier syncs reached, so a disk that returns synced pages as zeros is reported as corruption rather than read as free space. Needs `segment_bytes` above 8 KiB. Defaults to true.", + "request_connection_window_bytes": { + "description": "HTTP/2 connection window of a request connection (default 16 MiB).", "type": [ - "boolean", + "integer", "null" - ] + ], + "format": "uint32", + "minimum": 0.0 }, - "recovery_timeout_ms": { - "description": "How long log shard recovery may go without finishing another file before the shard fails (default 120 s). It does not bound the whole scan, which grows with the log.", + "request_connections": { + "description": "Connections per peer for unary requests, each carrying one peer channel (default 4).", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint", "minimum": 0.0 }, - "release_idle_payloads_after_ms": { - "description": "How long a volume replica appends nothing before its synced payloads leave memory; defaults to 5000.", + "request_stream_window_bytes": { + "description": "HTTP/2 stream window this worker grants a peer channel's replies (default 4 MiB). A worker's server grants each incoming stream a fixed 4 MiB window.", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint32", "minimum": 0.0 }, - "remove_segments_timeout_ms": { + "server_connection_capacity": { + "description": "TCP connections the internal HTTP listener may serve at once (default 8192).", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint", "minimum": 0.0 }, - "segment_bytes": { + "stream_connection_window_bytes": { + "description": "HTTP/2 connection window of a stream connection (default 32 MiB).", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint32", "minimum": 0.0 }, - "write_to_cold_at_disk_percent": { - "description": "Early cold-write watermark, 1..99 percent of the disk cap; defaults to 75.", + "stream_connections": { + "description": "Connections per peer for long-lived streams such as tunnels (default 2).", "type": [ "integer", "null" ], - "format": "uint8", + "format": "uint", "minimum": 0.0 }, - "write_to_disk_timeout_ms": { + "stream_stream_window_bytes": { + "description": "HTTP/2 stream window of a long-lived stream (default 1 MiB).", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint32", "minimum": 0.0 } }, "additionalProperties": false }, - "Logs": { + "Pegboard": { "type": "object", "properties": { - "redirect_logs_dir": { - "default": null, + "actor_index_buckets_per_name": { + "description": "Hashed index bucket volumes for each namespace and actor name (default 8, 1..=256).\n\nThis is part of the index address format. Changing it on a running cluster strands existing rows in buckets that listing and destroy no longer target, so treat it as fixed per cluster.", "type": [ - "string", + "integer", "null" - ] - } - }, - "additionalProperties": false - }, - "Metadata": { - "type": "object", - "required": [ - "project" - ], - "properties": { - "project": { - "type": "string" - } - }, - "additionalProperties": false - }, - "Metrics": { - "description": "Configuration for the metrics service.", - "type": "object", - "properties": { - "hardware": { - "description": "Host hardware metrics, including a short disk probe of each data directory at startup.", - "default": { - "disk_probe": null, - "disk_probe_bytes": null - }, - "allOf": [ - { - "$ref": "#/definitions/HardwareMetrics" - } - ] + ], + "format": "uint64", + "minimum": 0.0 }, - "host": { + "actor_index_list_concurrency": { + "description": "Maximum actor index bucket pages one listing reads at once (default 32).", "type": [ - "string", + "integer", "null" ], - "format": "ip" + "format": "uint", + "minimum": 0.0 }, - "port": { + "actor_index_reaper_max_concurrency": { + "description": "Lazy orphan deletes an actor listing runs at once (default 16).", "type": [ "integer", "null" ], - "format": "uint16", + "format": "uint", "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "ObjectStorageConfig": { - "type": "object", - "properties": { - "primary": { - "default": "in_memory", - "allOf": [ - { - "$ref": "#/definitions/ObjectStoreBackend" - } - ] }, - "read_first_attempt_ms": { - "description": "Milliseconds the first attempt of a small GET or HEAD may wait for response headers before the client cuts it off and retries it with its normal timeouts. A request on a stalled connection otherwise waits the full 30 s client timeout. Default 250, set from the load cluster's Azure account, where about 0.02% of small requests took longer; 0 disables it. Response bodies are never cut off.", - "default": null, + "actor_index_reaper_max_pending": { + "description": "Rows an actor listing's lazy orphan deletes may queue at once (default 1024).", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint", "minimum": 0.0 }, - "write_first_attempt_bytes_per_second": { - "description": "The upload rate a conditional PUT's first attempt may fall to before it is cut off, which extends `write_first_attempt_ms` by the body's size. Default 8 MiB/s.", - "default": null, + "actor_key_cache_capacity": { + "description": "Actor key reservations and key epochs cached in one process, each (default 100000). Reservations never change, so a cached one is kept until evicted.", "type": [ "integer", "null" @@ -2086,178 +1935,103 @@ "format": "uint64", "minimum": 0.0 }, - "write_first_attempt_ms": { - "description": "Milliseconds the first attempt of a small conditional PUT (a lease, heartbeat or manifest) may wait for response headers, before the upload time its body needs at `write_first_attempt_bytes_per_second`. Unset by default, which disables it. Healthy conditional PUT latency is calibrated only on Azure; a healthy GCS PUT can take over 250 ms. GCS also allows about one write per second to one object, so a retry shortly after a cut-off on the same lease or heartbeat object risks a 429, an unknown outcome and an extra readback. Set it only from measured conditional PUT latency of the backend.", - "default": null, + "actor_start_notice_timeout_ms": { + "description": "Timeout of one start notice to a waiting gateway worker. Unit is in milliseconds (default 2000, 100..=30000).", "type": [ "integer", "null" ], "format": "uint64", "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "ObjectStoreBackend": { - "oneOf": [ - { - "type": "string", - "enum": [ - "in_memory" - ] }, - { - "description": "A local directory, for a single engine process that keeps its data across restarts.", - "type": "object", - "required": [ - "file_system" + "actor_start_threshold": { + "description": "How long the engine waits after sending an actor's start for the node to report it running. Past it the start is given up: the node is told to stop that epoch, and the actor starts again once the node reports it stopped or is proven gone.\n\nUnit is in milliseconds (default 30000).", + "type": [ + "integer", + "null" ], - "properties": { - "file_system": { - "$ref": "#/definitions/FileSystemObjectStoreConfig" - } - }, - "additionalProperties": false + "format": "uint64", + "minimum": 0.0 }, - { - "type": "object", - "required": [ - "s3" + "actor_start_waiters_capacity": { + "description": "Gateway workers one actor keeps waiting for its start (default 64, 1..=1024). A request that finds the list full waits on its fallback poll alone.", + "type": [ + "integer", + "null" ], - "properties": { - "s3": { - "$ref": "#/definitions/S3ObjectStoreConfig" - } - }, - "additionalProperties": false + "format": "uint32", + "minimum": 0.0 }, - { - "type": "object", - "required": [ - "azure" - ], - "properties": { - "azure": { - "$ref": "#/definitions/AzureObjectStoreConfig" - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "gcs" - ], - "properties": { - "gcs": { - "$ref": "#/definitions/GcsObjectStoreConfig" - } - }, - "additionalProperties": false - } - ] - }, - "Outbound": { - "description": "Policy for outbound HTTP requests to user-configured destinations, such as serverless runner URLs.\n\nThese requests originate from inside the trusted engine network, so without restrictions a caller who can configure a runner can reach internal-only services. The defaults deny every non-globally-routable destination except loopback.", - "type": "object", - "properties": { - "allow_cidrs": { - "description": "Additional CIDRs that are always permitted, evaluated after `deny_cidrs`.\n\nUse this to reach a specific internal service without opening up the whole private range.", - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } - }, - "allow_hosts": { - "description": "Hostnames that are always permitted, whatever they resolve to.\n\nMatched exactly and case-insensitively, with no wildcards. Use this for a first-party service whose address is not known ahead of time, such as a Kubernetes service name. Anything served at a listed host becomes reachable by every runner config, so list individual hosts rather than a shared entry point.", + "actor_stop_threshold": { + "description": "How long a node may take to stop its actors once asked, advertised to the node on connect. A node shutting down drains its actors within this budget, and RivetKit uses it as the default shutdown grace period.\n\nUnit is in milliseconds (default 1800000, 30 minutes).", "type": [ - "array", + "integer", "null" ], - "items": { - "type": "string" - } - }, - "allow_insecure_scheme": { - "description": "Allow plaintext `http://` destinations. When disabled only `https://` is permitted.", - "type": [ - "boolean", - "null" - ] - }, - "allow_loopback": { - "description": "Allow destinations that resolve to loopback addresses (127.0.0.0/8, ::1).\n\nEnabled by default so local development against `http://localhost:...` works without configuration.", - "type": [ - "boolean", - "null" - ] + "format": "uint64", + "minimum": 0.0 }, - "allow_private_networks": { - "description": "Allow destinations that resolve to private, link-local, shared (CGNAT), or otherwise non-globally-routable addresses.\n\nSelf-hosted deployments that point runners at addresses on their own network, such as a Docker Compose service name, need this enabled.", - "type": [ - "boolean", - "null" + "command_concurrency": { + "description": "Per-class handler concurrency for the storage commands pegboard registers on storage workers.", + "default": { + "actor": null, + "actor_event": null, + "actor_read": null, + "index": null + }, + "allOf": [ + { + "$ref": "#/definitions/CommandConcurrency" + } ] }, - "deny_cidrs": { - "description": "Additional CIDRs that are always denied. Takes precedence over every allow rule.", + "gateway_port": { + "description": "Port for the new partition-backed gateway and node Hyper listener (default 6422).", "type": [ - "array", + "integer", "null" ], - "items": { - "type": "string" - } + "format": "uint16", + "minimum": 0.0 }, - "max_redirects": { - "description": "Maximum number of redirects to follow. Every hop is re-checked against this policy.", + "gateway_retry_budget_max_tokens": { + "description": "Retries one gateway process can bank for a burst of refusals; the budget starts full (default 100, 0..=100000).", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint32", "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "PeerTransport": { - "description": "Connections and flow-control windows per peer. Omitted values use the defaults.", - "type": "object", - "properties": { - "channel_large_request_bytes": { - "description": "Requests with a larger payload use a peer's large-request channels, so they never queue ahead of small requests on one stream (default 64 KiB).", + }, + "gateway_retry_budget_percent": { + "description": "Retries of refused requests one gateway process allows, as a percentage of the requests it receives (default 10, 0..=100). A refused request past this budget fails with `guard.service_unavailable` and its retry hint, so the client owns the next attempt.", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint32", "minimum": 0.0 }, - "channel_max_write_bytes": { - "description": "Most bytes a peer channel writes at once from its queue (default 256 KiB).", + "gateway_start_poll_after_ms": { + "description": "Time after a gateway request starts waiting for an actor's start notice before its first fallback read. Unit is in milliseconds (default 2000, 100..=30000).", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "channel_queue_bytes": { - "description": "Bytes of requests a peer channel queues for writing; a request that would exceed it is refused, though an empty queue always takes one (default 64 MiB).", + "gateway_start_poll_interval_ms": { + "description": "Time between later fallback reads while a gateway request waits for an actor's start. Unit is in milliseconds (default 2000, 100..=30000).", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "channel_queue_frames": { - "description": "Frames a peer channel queues for writing; a full queue refuses the request (default 8192).", + "gateway_start_waits_capacity": { + "description": "Actors one gateway process waits on at once for a start notice (default 65536, 1..=1048576). When full, a new request waits on its fallback poll alone.", "type": [ "integer", "null" @@ -2265,17 +2039,17 @@ "format": "uint", "minimum": 0.0 }, - "channel_reply_queue_bytes": { - "description": "Bytes of replies one served peer channel queues for writing. A channel at its cap refuses new requests as overloaded until its caller reads or the queued replies expire (default 64 MiB).", + "gateway_websocket_open_timeout_ms": { + "description": "Time an actor WebSocket upgrade may wait for its actor, as while storage recovers after an engine restart. Past it the gateway accepts the upgrade and closes it with `guard.service_unavailable` and a retry hint, so a client without a connect timeout retries instead of waiting forever. Unit is in milliseconds (default 15000, 1000..=45000).", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "reply_queue_bytes": { - "description": "Bytes of replies queued across every served peer channel of this worker. At the cap every channel refuses new requests as overloaded (default 1 GiB).", + "node_actor_handles_capacity": { + "description": "Retained actor handles per node connection (default 16384, 1..=65536).", "type": [ "integer", "null" @@ -2283,17 +2057,17 @@ "format": "uint", "minimum": 0.0 }, - "request_connection_window_bytes": { - "description": "HTTP/2 connection window of a request connection (default 16 MiB).", + "node_actor_inbound_capacity": { + "description": "Events, KV and SQLite requests queued from one actor on a node connection (default 128, 1..=65536).", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint", "minimum": 0.0 }, - "request_connections": { - "description": "Connections per peer for unary requests, each carrying one peer channel (default 4).", + "node_actor_lane_capacity": { + "description": "Commands and tunnel messages queued toward one actor on a node connection (default 128, 1..=65536).", "type": [ "integer", "null" @@ -2301,8 +2075,8 @@ "format": "uint", "minimum": 0.0 }, - "request_stream_window_bytes": { - "description": "HTTP/2 stream window this worker grants a peer channel's replies (default 4 MiB). A worker's server grants each incoming stream a fixed 4 MiB window.", + "node_connect_admission_burst": { + "description": "node connects one process can admit in a burst; the budget starts full (default 400, 1..=1000000).", "type": [ "integer", "null" @@ -2310,8 +2084,8 @@ "format": "uint32", "minimum": 0.0 }, - "stream_connection_window_bytes": { - "description": "HTTP/2 connection window of a stream connection (default 32 MiB).", + "node_connect_admissions_per_second": { + "description": "node connects one process admits per second once its burst is spent (default 200, 1..=100000). A connect past the budget is closed at once with `node.connect_overloaded` and a retry hint, before any work, so a fleet reconnecting after an outage cannot overwhelm guard.", "type": [ "integer", "null" @@ -2319,32 +2093,26 @@ "format": "uint32", "minimum": 0.0 }, - "stream_connections": { - "description": "Connections per peer for long-lived streams such as tunnels (default 2).", + "node_connect_retry_after_ms": { + "description": "Retry hint sent with a shed node connect. The node waits between one and two hints, so shed connects return spread out, and caps the hint at 5 s so a shed node still retries well inside the lost threshold. The same hint goes with a connect refused because storage could not register the node yet. Unit is in milliseconds (default 1000, 100..=5000).", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "stream_stream_window_bytes": { - "description": "HTTP/2 stream window of a long-lived stream (default 1 MiB).", + "node_directory_cache_ms": { + "description": "Maximum age of the process-local node directory that actor allocation reads instead of listing the node index on every allocation. Must be greater than 0.\n\nUnit is in milliseconds. Defaults to 1000.", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint64", "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "Pegboard": { - "type": "object", - "properties": { - "actor_index_buckets_per_name": { - "description": "Hashed index bucket volumes for each namespace and actor name (default 8, 1..=256).\n\nThis is part of the index address format. Changing it on a running cluster strands existing rows in buckets that listing and destroy no longer target, so treat it as fixed per cluster.", + }, + "node_directory_max_stale_ms": { + "description": "Maximum age of a node directory listing that allocation still uses while one background listing replaces it. Allocation waits for a listing only past this age. Must be at least `node_directory_cache_ms`.\n\nUnit is in milliseconds. Defaults to 5000.", "type": [ "integer", "null" @@ -2352,17 +2120,17 @@ "format": "uint64", "minimum": 0.0 }, - "actor_index_list_concurrency": { - "description": "Maximum actor index bucket pages one listing reads at once (default 32).", + "node_event_delivery_timeout_ms": { + "description": "Time a lifecycle event may spend retrying storage command deadlines before its node socket is closed for reconnection. Defaults to 120000 ms.", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "actor_index_reaper_max_concurrency": { - "description": "Lazy orphan deletes an actor listing runs at once (default 16).", + "node_index_reaper_max_concurrency": { + "description": "Stale node row deletes one reader runs at once (default 8).", "type": [ "integer", "null" @@ -2370,8 +2138,8 @@ "format": "uint", "minimum": 0.0 }, - "actor_index_reaper_max_pending": { - "description": "Rows an actor listing's lazy orphan deletes may queue at once (default 1024).", + "node_index_reaper_max_pending": { + "description": "Stale node row deletes one reader may queue at once (default 256).", "type": [ "integer", "null" @@ -2379,8 +2147,8 @@ "format": "uint", "minimum": 0.0 }, - "actor_key_cache_capacity": { - "description": "Actor key reservations and key epochs cached in one process, each (default 100000). Reservations never change, so a cached one is kept until evicted.", + "node_lost_threshold": { + "description": "How long a disconnected node keeps its actors before stopping them, advertised to the node on connect. The engine waits as long after a connection closes before it judges the node's actors lost, so both sides agree. It must exceed the node client's longest reconnect backoff (30 s), or an engine restart stops every actor.\n\nUnit is in milliseconds (default 40000).", "type": [ "integer", "null" @@ -2388,49 +2156,34 @@ "format": "uint64", "minimum": 0.0 }, - "actor_start_notice_timeout_ms": { - "description": "Timeout of one start notice to a waiting gateway worker. Unit is in milliseconds (default 2000, 100..=30000).", + "node_ping_timeout": { + "description": "Max time since last pong before the node connection is terminated. Unit is in milliseconds.", "type": [ "integer", "null" ], - "format": "uint64", - "minimum": 0.0 + "format": "int64" }, - "actor_start_waiters_capacity": { - "description": "Gateway workers one actor keeps waiting for its start (default 64, 1..=1024). A request that finds the list full waits on its fallback poll alone.", + "node_record_cache_capacity": { + "description": "node records cached for routing fallbacks in one process (default 10000).", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint64", "minimum": 0.0 }, - "command_concurrency": { - "description": "Per-class handler concurrency for the Depot commands pegboard registers on storage workers.", - "default": { - "actor": null, - "actor_event": null, - "actor_read": null, - "index": null - }, - "allOf": [ - { - "$ref": "#/definitions/CommandConcurrency" - } - ] - }, - "envoy_actor_inbound_capacity": { - "description": "Events, KV and SQLite requests queued from one actor on an Envoy connection (default 128, 1..=65536).", + "node_record_cache_ms": { + "description": "Lifetime of a cached node record read on a routing fallback, in milliseconds (default 2000).", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "envoy_actor_lane_capacity": { - "description": "Commands and tunnel messages queued toward one actor on an Envoy connection (default 128, 1..=65536).", + "node_socket_queue_capacity": { + "description": "Messages queued for one node socket writer (default 128, 1..=65536).", "type": [ "integer", "null" @@ -2438,26 +2191,26 @@ "format": "uint", "minimum": 0.0 }, - "envoy_connect_admission_burst": { - "description": "Envoy connects one process can admit in a burst; the budget starts full (default 400, 1..=1000000).", + "node_start_wait_ms": { + "description": "Longest time a node connection holds a gateway request for an actor generation whose start command it has not forwarded yet, in milliseconds (default 1000). A gateway sends a request right behind the start, so this keeps the request from reaching the node first. When it runs out the request is forwarded anyway, and the node refuses it as not found.", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint64", "minimum": 0.0 }, - "envoy_connect_admissions_per_second": { - "description": "Envoy connects one process admits per second once its burst is spent (default 200, 1..=100000). A connect past the budget is closed at once with `envoy.connect_overloaded` and a retry hint, before any work, so a fleet reconnecting after an outage cannot overwhelm guard.", + "node_tunnel_queue_capacity": { + "description": "Messages queued toward one gateway tunnel stream on a node connection (default 128, 1..=65536).", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint", "minimum": 0.0 }, - "envoy_connect_retry_after_ms": { - "description": "Retry hint sent with a shed Envoy connect. The Envoy waits between one and two hints, so shed connects return spread out, and caps the hint at 5 s so a shed runner still retries well inside the lost threshold. The same hint goes with a connect refused because storage could not register the Envoy yet. Unit is in milliseconds (default 1000, 100..=5000).", + "node_update_ping_interval": { + "description": "Ping interval for node updates in milliseconds.", "type": [ "integer", "null" @@ -2465,8 +2218,8 @@ "format": "uint64", "minimum": 0.0 }, - "envoy_directory_cache_ms": { - "description": "Maximum age of the process-local Envoy directory that actor allocation reads instead of listing the Envoy index on every allocation. Must be greater than 0.\n\nUnit is in milliseconds. Defaults to 1000.", + "sqlite_remote_idle_ms": { + "description": "Idle time after which a remote SQL session is closed and reopened on next use.\n\nUnit is in milliseconds (default 30000).", "type": [ "integer", "null" @@ -2474,44 +2227,48 @@ "format": "uint64", "minimum": 0.0 }, - "envoy_directory_max_stale_ms": { - "description": "Maximum age of an Envoy directory listing that allocation still uses while one background listing replaces it. Allocation waits for a listing only past this age. Must be at least `envoy_directory_cache_ms`.\n\nUnit is in milliseconds. Defaults to 5000.", + "sqlite_remote_max_response_bytes": { + "description": "Largest response, in logical bytes, that one remote SQL request may return. A larger result fails the request instead of being sent.\n\nUnit is in bytes (default 25165824, 24 MiB; at most 64 MiB).", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint", "minimum": 0.0 }, - "envoy_event_delivery_timeout_ms": { - "description": "Time a lifecycle event may spend retrying storage command deadlines before its Envoy socket is closed for reconnection. Defaults to 120000 ms.", + "sqlite_remote_worker_threads": { + "description": "Threads shared by every remote SQL session in this process (default 4).", "type": [ "integer", "null" ], - "format": "uint64", + "format": "uint", "minimum": 0.0 }, - "envoy_index_reaper_max_concurrency": { - "description": "Stale Envoy row deletes one reader runs at once (default 8).", + "sqlite_server_prefetch": { + "description": "Sends SQLite pages the client is likely to read next along with the pages it asked for (default true). When off, the engine sends only requested pages but keeps maintaining its prefetch hints, so turning it back on needs no rebuild. Runtime configurable.", "type": [ - "integer", + "boolean", "null" - ], - "format": "uint", - "minimum": 0.0 + ] }, - "envoy_index_reaper_max_pending": { - "description": "Stale Envoy row deletes one reader may queue at once (default 256).", + "sqlite_sessions": { + "description": "Maximum actor storage lanes retained by one node connection (default 4000). Explicit overrides must be positive; each lane retains its database volume until stop.", "type": [ "integer", "null" ], "format": "uint", "minimum": 0.0 - }, - "envoy_lost_checks_capacity": { - "description": "Lost checks one process holds for closed Envoy connections that may not reconnect (default 4096, 1..=65536). When full, the check due soonest is dropped and its actors are found lost on their next request.", + } + }, + "additionalProperties": false + }, + "ProcessClassCapacity": { + "description": "The process-wide caps of a class that travels on unreserved subjects.", + "type": "object", + "properties": { + "incoming_capacity": { "type": [ "integer", "null" @@ -2519,238 +2276,47 @@ "format": "uint", "minimum": 0.0 }, - "envoy_lost_threshold": { - "description": "How long a disconnected Envoy keeps its actors before stopping them, advertised to the Envoy on connect. The engine waits as long after a connection closes before it judges the Envoy's actors lost, so both sides agree. It must exceed the Envoy client's longest reconnect backoff (30 s), or an engine restart stops every actor.\n\nUnit is in milliseconds (default 40000).", + "outgoing_capacity": { "type": [ "integer", "null" ], - "format": "int64" + "format": "uint", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "PubSub": { + "description": "Exact-subject worker requests and streams.", + "type": "object", + "properties": { + "classes": { + "description": "Per-class request caps. Every class has a defined cap; omitted values use the defaults.", + "anyOf": [ + { + "$ref": "#/definitions/RequestClasses" + }, + { + "type": "null" + } + ] }, - "envoy_ping_timeout": { - "description": "Max time since last pong before the envoy connection is terminated. Unit is in milliseconds.", + "max_message_bytes": { "type": [ "integer", "null" ], - "format": "int64" + "format": "uint", + "minimum": 0.0 }, - "envoy_record_cache_capacity": { - "description": "Envoy records cached for routing fallbacks in one process (default 10000).", + "max_request_subjects": { + "description": "Maximum concurrently reserved request subjects with isolated capacity.", "type": [ "integer", "null" ], - "format": "uint64", - "minimum": 0.0 - }, - "envoy_record_cache_ms": { - "description": "Lifetime of a cached Envoy record read on a routing fallback, in milliseconds (default 2000).", - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0.0 - }, - "envoy_socket_queue_capacity": { - "description": "Messages queued for one Envoy socket writer (default 128, 1..=65536).", - "type": [ - "integer", - "null" - ], - "format": "uint", - "minimum": 0.0 - }, - "envoy_start_wait_ms": { - "description": "Longest time an Envoy connection holds a gateway request for an actor generation whose start command it has not forwarded yet, in milliseconds (default 1000). A gateway sends a request right behind the start, so this keeps the request from reaching the Envoy first. When it runs out the request is forwarded anyway, and the Envoy refuses it as not found.", - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0.0 - }, - "envoy_tunnel_queue_capacity": { - "description": "Messages queued toward one gateway tunnel stream on an Envoy connection (default 128, 1..=65536).", - "type": [ - "integer", - "null" - ], - "format": "uint", - "minimum": 0.0 - }, - "envoy_update_ping_interval": { - "description": "Ping interval for envoy updates in milliseconds.", - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0.0 - }, - "gateway_port": { - "description": "Port for the new partition-backed gateway and Envoy Hyper listener (default 6422).", - "type": [ - "integer", - "null" - ], - "format": "uint16", - "minimum": 0.0 - }, - "gateway_retry_budget_max_tokens": { - "description": "Retries one gateway process can bank for a burst of refusals; the budget starts full (default 100, 0..=100000).", - "type": [ - "integer", - "null" - ], - "format": "uint32", - "minimum": 0.0 - }, - "gateway_retry_budget_percent": { - "description": "Retries of refused requests one gateway process allows, as a percentage of the requests it receives (default 10, 0..=100). A refused request past this budget fails with `guard.service_unavailable` and its retry hint, so the client owns the next attempt.", - "type": [ - "integer", - "null" - ], - "format": "uint32", - "minimum": 0.0 - }, - "gateway_start_poll_after_ms": { - "description": "Time after a gateway request starts waiting for an actor's start notice before its first fallback read. Unit is in milliseconds (default 2000, 100..=30000).", - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0.0 - }, - "gateway_start_poll_interval_ms": { - "description": "Time between later fallback reads while a gateway request waits for an actor's start. Unit is in milliseconds (default 2000, 100..=30000).", - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0.0 - }, - "gateway_start_waits_capacity": { - "description": "Actors one gateway process waits on at once for a start notice (default 65536, 1..=1048576). When full, a new request waits on its fallback poll alone.", - "type": [ - "integer", - "null" - ], - "format": "uint", - "minimum": 0.0 - }, - "gateway_websocket_open_timeout_ms": { - "description": "Time an actor WebSocket upgrade may wait for its actor, as while storage recovers after an engine restart. Past it the gateway accepts the upgrade and closes it with `guard.service_unavailable` and a retry hint, so a client without a connect timeout retries instead of waiting forever. Unit is in milliseconds (default 15000, 1000..=45000).", - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0.0 - }, - "sqlite_remote_idle_ms": { - "description": "Idle time after which a remote SQL session is closed and reopened on next use.\n\nUnit is in milliseconds (default 30000).", - "type": [ - "integer", - "null" - ], - "format": "uint64", - "minimum": 0.0 - }, - "sqlite_remote_max_response_bytes": { - "description": "Largest response, in logical bytes, that one remote SQL request may return. A larger result fails the request instead of being sent.\n\nUnit is in bytes (default 25165824, 24 MiB; at most 64 MiB).", - "type": [ - "integer", - "null" - ], - "format": "uint", - "minimum": 0.0 - }, - "sqlite_remote_worker_threads": { - "description": "Threads shared by every remote SQL session in this process (default 4).", - "type": [ - "integer", - "null" - ], - "format": "uint", - "minimum": 0.0 - }, - "sqlite_server_prefetch": { - "description": "Sends SQLite pages the client is likely to read next along with the pages it asked for (default true). When off, the engine sends only requested pages but keeps maintaining its prefetch hints, so turning it back on needs no rebuild. Runtime configurable.", - "type": [ - "boolean", - "null" - ] - }, - "sqlite_sessions": { - "description": "Maximum SQLite actor sessions retained by one Envoy connection (default 256).", - "type": [ - "integer", - "null" - ], - "format": "uint", - "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "ProcessClassCapacity": { - "description": "The process-wide caps of a class that travels on unreserved subjects.", - "type": "object", - "properties": { - "incoming_capacity": { - "type": [ - "integer", - "null" - ], - "format": "uint", - "minimum": 0.0 - }, - "outgoing_capacity": { - "type": [ - "integer", - "null" - ], - "format": "uint", - "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "PubSub": { - "description": "Exact-subject worker requests and streams.", - "type": "object", - "properties": { - "classes": { - "description": "Per-class request caps. Every class has a defined cap; omitted values use the defaults.", - "anyOf": [ - { - "$ref": "#/definitions/RequestClasses" - }, - { - "type": "null" - } - ] - }, - "max_message_bytes": { - "type": [ - "integer", - "null" - ], - "format": "uint", - "minimum": 0.0 - }, - "max_request_subjects": { - "description": "Maximum concurrently reserved request subjects with isolated capacity.", - "type": [ - "integer", - "null" - ], - "format": "uint", + "format": "uint", "minimum": 0.0 }, "peer_transport": { @@ -2761,10 +2327,13 @@ "channel_queue_bytes": null, "channel_queue_frames": null, "channel_reply_queue_bytes": null, + "incoming_channel_capacity": null, + "outgoing_channel_capacity": null, "reply_queue_bytes": null, "request_connection_window_bytes": null, "request_connections": null, "request_stream_window_bytes": null, + "server_connection_capacity": null, "stream_connection_window_bytes": null, "stream_connections": null, "stream_stream_window_bytes": null @@ -2815,7 +2384,7 @@ "additionalProperties": false }, "RequestClasses": { - "description": "Per-class request caps. Depot classes travel on reserved subjects whose window is their incoming cap, so they take only an outgoing cap across every target.", + "description": "Per-class request caps. storage classes travel on reserved subjects whose window is their incoming cap, so they take only an outgoing cap across every target.", "type": "object", "properties": { "actor_start_notice": { @@ -2829,41 +2398,41 @@ } ] }, - "depot_coordinator": { - "description": "Depot tablet coordinator requests (default outgoing 1024).", + "gateway_http": { + "description": "Gateway HTTP tunnels (default 4096 each way).", "anyOf": [ { - "$ref": "#/definitions/SubjectClassCapacity" + "$ref": "#/definitions/ProcessClassCapacity" }, { "type": "null" } ] }, - "depot_kv_command": { - "description": "Depot KV commands (default outgoing 8192).", + "gateway_websocket": { + "description": "Gateway WebSocket tunnels, held for the socket's life (default 65536 each way).", "anyOf": [ { - "$ref": "#/definitions/SubjectClassCapacity" + "$ref": "#/definitions/ProcessClassCapacity" }, { "type": "null" } ] }, - "depot_log": { - "description": "Depot log shard requests (default outgoing 8192).", + "node_command": { + "description": "Actor commands to node connections (default 4096 each way).", "anyOf": [ { - "$ref": "#/definitions/SubjectClassCapacity" + "$ref": "#/definitions/ProcessClassCapacity" }, { "type": "null" } ] }, - "depot_stop_readiness": { - "description": "Depot stop-readiness checks (default outgoing 1024).", + "storage_coordinator": { + "description": "storage partition coordinator requests (default outgoing 1024).", "anyOf": [ { "$ref": "#/definitions/SubjectClassCapacity" @@ -2873,8 +2442,8 @@ } ] }, - "depot_volume": { - "description": "Depot volume lifecycle and filesystem requests (default outgoing 4096).", + "storage_kv_command": { + "description": "storage KV commands (default outgoing 8192).", "anyOf": [ { "$ref": "#/definitions/SubjectClassCapacity" @@ -2884,33 +2453,33 @@ } ] }, - "envoy_command": { - "description": "Actor commands to envoy connections (default 4096 each way).", + "storage_log": { + "description": "storage log shard requests (default outgoing 8192).", "anyOf": [ { - "$ref": "#/definitions/ProcessClassCapacity" + "$ref": "#/definitions/SubjectClassCapacity" }, { "type": "null" } ] }, - "gateway_http": { - "description": "Gateway HTTP tunnels (default 4096 each way).", + "storage_stop_readiness": { + "description": "storage stop-readiness checks (default outgoing 1024).", "anyOf": [ { - "$ref": "#/definitions/ProcessClassCapacity" + "$ref": "#/definitions/SubjectClassCapacity" }, { "type": "null" } ] }, - "gateway_websocket": { - "description": "Gateway WebSocket tunnels, held for the socket's life (default 65536 each way).", + "storage_volume": { + "description": "storage volume lifecycle and filesystem requests (default outgoing 4096).", "anyOf": [ { - "$ref": "#/definitions/ProcessClassCapacity" + "$ref": "#/definitions/SubjectClassCapacity" }, { "type": "null" @@ -2932,19 +2501,548 @@ "format": "uint32", "minimum": 0.0 }, - "interval_ms": { - "type": "integer", + "interval_ms": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "Runtime": { + "type": "object", + "properties": { + "force_shutdown_duration": { + "description": "Time (in seconds) after which the engine process will forcibly exit after receiving SIGTERM. Must be greater than or equal to both worker_shutdown_duration and guard_shutdown_duration. Defaults to nine minutes and 50 seconds, allowing the storage stop wait, singleton handover and teardown reserve.", + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "guard_shutdown_duration": { + "description": "Time (in seconds) to allow for guard to wait for pending requests after receiving SIGTERM. Defaults to nine minutes.", + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "worker_cpu_max": { + "description": "Adjusts worker curve around this value (in millecores, i.e. 1000 = 1 core). Is not a hard limit. When unset, uses /sys/fs/cgroup/cpu.max, and if that is unset uses total host cpu.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "worker_max_concurrent_workflows": { + "description": "Maximum concurrently running workflows of a given workflow name for the **entire cluster**.", + "type": [ + "object", + "null" + ], + "additionalProperties": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + } + }, + "worker_max_deduped_workflows_per_pull": { + "description": "Maximum deduplicated workflows considered in a single pull. Defaults to 10000.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "worker_max_wake_condition_clears_per_pull": { + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "worker_max_wake_keys_per_workflow_name_per_pull": { + "description": "Maximum wake condition keys read per workflow name in a single pull. Defaults to 20000, or 5000 for the storage compaction workflows. Set the \"default\" key to apply to all workflow names.", + "type": [ + "object", + "null" + ], + "additionalProperties": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + } + }, + "worker_max_workflows_per_pull": { + "description": "Maximum wake condition keys a worker clears when leasing workflows in a single pull. Defaults to 40000. Maximum workflows a worker attempts to lease in a single pull. Defaults to 1000.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "worker_poll_interval_ms": { + "description": "Poll interval for pulling workflows and deciding whether a short sleep stays in memory. Unit is in milliseconds. Defaults to 16000.", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "worker_shutdown_duration": { + "description": "Time (in seconds) to allow for the gasoline worker engine to stop gracefully after receiving SIGTERM. Defaults to 30 seconds.", + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "S3ObjectStoreConfig": { + "type": "object", + "required": [ + "bucket" + ], + "properties": { + "access_key_id": { + "default": null, + "type": [ + "string", + "null" + ] + }, + "bucket": { + "type": "string" + }, + "endpoint": { + "default": null, + "type": [ + "string", + "null" + ] + }, + "prefix": { + "default": null, + "type": [ + "string", + "null" + ] + }, + "region": { + "default": null, + "type": [ + "string", + "null" + ] + }, + "secret_access_key": { + "default": null, + "anyOf": [ + { + "$ref": "#/definitions/Secret" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + }, + "Secret": { + "type": "string" + }, + "StorageConfig": { + "type": "object", + "properties": { + "alarms": { + "description": "Bounded, deadline-driven volume alarm delivery.", + "default": { + "handler_timeout_ms": null, + "io_timeout_ms": null, + "max_callbacks": null, + "max_candidates": null, + "max_operations": null, + "page_size": null, + "retry_max_ms": null, + "retry_min_ms": null + }, + "allOf": [ + { + "$ref": "#/definitions/AlarmConfig" + } + ] + }, + "auto_provision_partitions": { + "description": "Creates this many partitions over this storage worker when the cluster has none, so a single-process engine serves actors without an operator. A restart finishes a run that stopped partway; partitions it did not start are left alone. Clusters with several storage workers leave it unset and run `storage partition provision` instead.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "balancing": { + "default": { + "destination_stability_ms": 60000, + "enabled": true, + "max_disk_probes": 4, + "missing_worker_ms": 120000, + "partitions_per_core": 2 + }, + "allOf": [ + { + "$ref": "#/definitions/PartitionBalancingConfig" + } + ] + }, + "bulk_read_bytes_per_sec": { + "description": "Bytes per second that bulk runs may read across every partition of this process, with a burst of a quarter second (at least 4 MiB). Bulk runs wait for their bytes; point reads never wait. Unset or 0 leaves bulk runs unpaced.", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "bulk_read_cache_blocks": { + "description": "Whether SST blocks a bulk run fetches enter the shared block cache. Defaults to true; false keeps large scans from evicting other volumes' hot blocks.", + "type": [ + "boolean", + "null" + ] + }, + "bulk_read_fetch_tasks": { + "description": "Concurrent SST block fetches inside one bulk run's scan. Defaults to 1; 0 is treated as 1.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "bulk_read_min_chunks": { + "description": "Chunk runs of at least this many chunks (4 KiB each) are read with the bulk scan settings below, as a table scan's read-ahead windows are. Unset or 0 reads every run with the normal settings.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "checkpoints": { + "default": { + "max_named_checkpoints_per_volume": 64, + "retention": null + }, + "allOf": [ + { + "$ref": "#/definitions/CheckpointConfig" + } + ] + }, + "cold_store": { + "default": { + "block_cache_bytes": null, + "compacted_sst_bytes": null, + "disk_cache_bytes": null, + "disk_cache_directory": null, + "disk_cache_on_compaction": null, + "disk_cache_on_flush": null, + "disk_cache_part_bytes": null, + "l0_max_ssts": null, + "max_concurrent_compactions": null, + "meta_cache_bytes": null, + "unflushed_budget_bytes": null + }, + "allOf": [ + { + "$ref": "#/definitions/ColdStoreConfig" + } + ] + }, + "cold_store_compression": { + "description": "Codec for SlateDB SST blocks in the cold store; defaults to `lz4`. Each SST records its own codec, so changing it keeps existing SSTs readable.", + "anyOf": [ + { + "$ref": "#/definitions/ColdStoreCompression" + }, + { + "type": "null" + } + ] + }, + "command_timeout_ms": { + "description": "Floor for every typed storage command deadline, in milliseconds. Each command keeps its own default (5 seconds generic, 30 seconds for actor storage); when set, the larger of the two bounds both the client's retry budget and the maintainer's handler timeout. Unset keeps the per-command defaults.", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "coordinator_request_capacity": { + "description": "Exact coordinator subject capacity. Defaults to 256.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "durable_max_events_per_commit": { + "description": "Most events of one durable state machine applied in one commit. Events that arrive while a commit is in flight are grouped up to this bound. Defaults to 16.", + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "endpoint_cache_capacity": { + "description": "Maximum cached endpoint hints, including missing workers. Defaults to 4096.", + "default": null, + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "filesystem": { + "default": { + "max_cache_bytes": 8388608, + "max_conflict_window_bytes": 4194304, + "max_memory_bytes": 67108864, + "max_operation_bytes": 8388608, + "max_pending_commits": 128, + "max_process_cache_bytes": 1073741824, + "max_snapshot_age_ms": 30000, + "max_snapshots": 128, + "max_transaction_age_ms": 300000, + "max_transaction_bytes": 134217728, + "max_unapplied_bytes": 268435456, + "max_value_bytes": 1048576, + "note_ttl_ms": 1000, + "request_timeout_ms": 30000 + }, + "allOf": [ + { + "$ref": "#/definitions/FilesystemConfig" + } + ] + }, + "flush_piggyback_min_bytes": { + "description": "Unflushed applied bytes at which a volume joins a partition flush another volume requested. Defaults to 16 KiB.", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "flush_stage_concurrency": { + "description": "Volume records whose old rows one partition filesystem flush reads at once while it stages. Staging excludes every other store operation of the partition. Defaults to 16.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "forks": { + "default": { + "check_grace_ms": 60000, + "materialize_batch_chunks": 1024, + "max_concurrent_materializations": 2 + }, + "allOf": [ + { + "$ref": "#/definitions/ForkConfig" + } + ] + }, + "heartbeat_gc": { + "description": "Background heartbeat reclamation; separate from membership lease expiration.", + "default": { + "batch_interval_ms": null, + "batch_size": null, + "batch_timeout_ms": null, + "delete_concurrency": null, + "pass_interval_ms": null, + "retention_ms": null + }, + "allOf": [ + { + "$ref": "#/definitions/HeartbeatGcConfig" + } + ] + }, + "idle_unload_after_ms": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "kv_commands": { + "default": { + "evicted_idle_warn_ms": null, + "max_command_bytes": null, + "max_eviction_closes": null, + "max_inflight_command_bytes": null, + "max_inflight_commands": null, + "max_open_volumes": null, + "max_worker_open_volume_bytes": null, + "max_worker_open_volumes": null, + "request_capacity": null, + "short_idle_close_ms": null, + "volume_idle_close_ms": null + }, + "allOf": [ + { + "$ref": "#/definitions/KvCommandConfig" + } + ] + }, + "learning_deadline_ms": { + "description": "How long a partition replica-set change may stay in Learning before the coordinator aborts it and the partition returns to its old members. Defaults to one hour and must be at least 45 minutes. It counts from the phase's start, not from the learner's progress, so it must outlast the membership holder wait (15 minutes) plus the copy of the largest log suffix a learner may have to catch up.", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "log_client_inflight_per_worker": { + "description": "Log shard requests a client keeps in flight to one storage worker. Later requests queue and go out together as one batch when a slot frees. Defaults to 2.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "log_directory": { + "description": "Existing directory owned by one storage process. Required when storage services start.", + "type": [ + "string", + "null" + ] + }, + "log_request_capacity": { + "description": "Exact replica subject capacity, shared by local clients and the shard. Defaults to 2048.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "log_shard": { + "description": "Optional overrides for the shard's disk, memory and operation bounds.", + "default": { + "checkpoint_bytes": null, + "checkpoint_timeout_ms": null, + "disk_read_concurrency": null, + "inbox_capacity": null, + "manifest_refresh_timeout_ms": null, + "max_admission_wait_ms": null, + "max_append_admission_wait_ms": null, + "max_batch_bytes": null, + "max_disk_bytes": null, + "max_disk_reads": null, + "max_loaded_volume_bytes": null, + "max_loaded_volumes": null, + "max_memory_bytes": null, + "max_memory_requests": null, + "max_retained_payload_bytes": null, + "max_retained_payload_bytes_per_volume": null, + "max_write_bytes": null, + "overload_retry_after_ms": null, + "preallocate_segments": null, + "recovery_timeout_ms": null, + "release_idle_payloads_after_ms": null, + "remove_segments_timeout_ms": null, + "segment_bytes": null, + "write_to_cold_at_disk_percent": null, + "write_to_disk_timeout_ms": null + }, + "allOf": [ + { + "$ref": "#/definitions/LogShardConfig" + } + ] + }, + "lookup_request_capacity": { + "description": "Concurrent topology endpoint lookups and heartbeat inspections admitted per process. Defaults to 128.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "maintainer_inbox_capacity": { + "description": "Queued events one partition maintainer accepts before it rejects new requests as overloaded. Every volume open, read, apply and status notice for the partition passes through it, so a burst of actor starts on one partition needs room for several events per start. Must be positive. Defaults to 4096.", + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "maintainer_max_loaded_volumes": { + "description": "Volumes one partition maintainer holds loaded at once, before opens of more are refused as overloaded. A loaded volume costs about 1.8 KiB of maintainer heap, so the default of 500,000 holds under 1 GiB per partition. Must be positive.", + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "maintainer_max_queued_opens": { + "description": "Volume opens queued in one partition maintainer's inbox, not yet taken by its processing task, at which a new open is refused as overloaded at once instead of joining the inbox. Other inbox events do not count. Opens queued past this would mostly expire before admission. Must be positive. Defaults to 1024.", + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "maintainer_max_requests": { + "description": "Client requests one partition maintainer tracks at once before it rejects more as overloaded. Must be positive. Defaults to 1024.", + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "manifest_refresh_ms": { + "description": "Fallback interval for re-reading the partition manifest. Routing misses and `NotMaintainer` replies refresh it at once. Defaults to 30 seconds.", + "type": [ + "integer", + "null" + ], "format": "uint64", "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "Runtime": { - "type": "object", - "properties": { - "force_shutdown_duration": { - "description": "Time (in seconds) after which the engine process will forcibly exit after receiving SIGTERM. Must be greater than or equal to both worker_shutdown_duration and guard_shutdown_duration. Defaults to 35 minutes, allowing the Depot stop wait and teardown reserve.", + }, + "max_background_cold_reads": { + "description": "Size of each background cold-read window per partition maintainer: held-image source reads for forks, replica log reads for applies, fork jobs and fork cleanup jobs are each bounded by it separately, so they never take client read slots. Defaults to 4.", "type": [ "integer", "null" @@ -2952,8 +3050,8 @@ "format": "uint32", "minimum": 0.0 }, - "guard_shutdown_duration": { - "description": "Time (in seconds) to allow for guard to wait for pending requests after receiving SIGTERM. Defaults to 10 minutes.", + "max_cold_reads": { + "description": "Client cold-store reads in flight per partition maintainer: session opens, lifecycle row lookups and session reads share this window. A cold wake's reads fan out through it, so a narrow window serializes them. Object storage throughput scales almost linearly to about 32 parallel GETs, and a read slot is not always a GET, so 64 keeps a cold wake's reads from waiting on slots; on the load cluster a fully cold wake took about 850 ms at 4, 430 ms at 64 and 390 ms at 512. Defaults to 64.", "type": [ "integer", "null" @@ -2961,8 +3059,17 @@ "format": "uint32", "minimum": 0.0 }, - "worker_cpu_max": { - "description": "Adjusts worker curve around this value (in millecores, i.e. 1000 = 1 core). Is not a hard limit. When unset, uses /sys/fs/cgroup/cpu.max, and if that is unset uses total host cpu.", + "max_cold_reads_per_volume": { + "description": "Client session reads of one volume a partition maintainer admits while reads of other volumes wait, so one large scan cannot hold every client cold-read slot. Slots no other volume waits for still go to that volume. Unset or 0 admits client reads in arrival order.", + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "max_read_sessions": { + "description": "Filesystem read sessions per partition maintainer. A session lives while its volume is being read and ends after `read_session_idle_ms` without a read, so this bounds how many volumes a partition serves reads for at once. Opens past it are refused as overloaded. A held session retains about 1.2 KiB of maintainer heap, so the default of 16,384 holds under 20 MiB per partition. Must be positive.", "type": [ "integer", "null" @@ -2970,58 +3077,53 @@ "format": "uint", "minimum": 0.0 }, - "worker_max_concurrent_workflows": { - "description": "Maximum concurrently running workflows of a given workflow name for the **entire cluster**.", + "membership_refresh_cooldown_ms": { + "description": "Minimum milliseconds between miss-triggered membership refresh attempts, including failures.", "type": [ - "object", + "integer", "null" ], - "additionalProperties": { - "type": "integer", - "format": "uint", - "minimum": 0.0 - } + "format": "uint64", + "minimum": 0.0 }, - "worker_max_deduped_workflows_per_pull": { - "description": "Maximum deduplicated workflows considered in a single pull. Defaults to 10000.", + "memtable_flush_throttle_ms": { + "description": "Throttle for memtable flushes that nobody urgently waits on: a pass that comes due waits up to this long, so passes that come due close together share one upload and one L0 SST. Defaults to ten seconds.", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "worker_max_wake_condition_clears_per_pull": { + "read_cursor_session_idle_ms": { + "description": "How long a session opened at the latest position stays registered after its last read, in milliseconds. An HTTP directory cursor resumes such a session between pages, and no client reopens it at its position, so a paging client keeps its cursor for this long between pages. Must be positive. Defaults to 30,000, the session lifetime.", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "worker_max_wake_keys_per_workflow_name_per_pull": { - "description": "Maximum wake condition keys read per workflow name in a single pull. Defaults to 20000, or 5000 for the depot compaction workflows. Set the \"default\" key to apply to all workflow names.", + "read_session_idle_ms": { + "description": "How long a read session stays registered after its last read, in milliseconds. Each read extends it up to the session's lifetime, and a client reopens an ended session on its next read, so sessions track volumes being read rather than volumes open. Must be positive. Defaults to 2,000.", "type": [ - "object", + "integer", "null" ], - "additionalProperties": { - "type": "integer", - "format": "uint", - "minimum": 0.0 - } + "format": "uint64", + "minimum": 0.0 }, - "worker_max_workflows_per_pull": { - "description": "Maximum wake condition keys a worker clears when leasing workflows in a single pull. Defaults to 40000. Maximum workflows a worker attempts to lease in a single pull. Defaults to 1000.", + "simulated_fs_read_cost_us": { + "description": "Simulation only: processing time each filesystem read request costs a partition maintainer, in microseconds, spent on the simulated clock so a maintainer busy with reads queues them as a loaded one does. Unset in deployments, where real processing time passes on its own.", "type": [ "integer", "null" ], - "format": "uint", + "format": "uint64", "minimum": 0.0 }, - "worker_poll_interval_ms": { - "description": "Poll interval for pulling workflows and deciding whether a short sleep stays in memory. Unit is in milliseconds. Defaults to 16000.", + "stop_poll_ms": { + "description": "Stop-permit retry interval. Defaults to one second.", "type": [ "integer", "null" @@ -3029,74 +3131,137 @@ "format": "uint64", "minimum": 0.0 }, - "worker_shutdown_duration": { - "description": "Time (in seconds) to allow for the gasoline worker engine to stop gracefully after receiving SIGTERM. Defaults to 30 seconds.", + "stop_teardown_ms": { + "description": "Teardown budget after a stop permit or timeout. Defaults to one minute.", "type": [ "integer", "null" ], - "format": "uint32", + "format": "uint64", "minimum": 0.0 - } - }, - "additionalProperties": false - }, - "S3ObjectStoreConfig": { - "type": "object", - "required": [ - "bucket" - ], - "properties": { - "access_key_id": { - "default": null, + }, + "stop_timeout_ms": { + "description": "Maximum coordinated stop wait from the first signal. Defaults to eight minutes.", "type": [ - "string", + "integer", "null" - ] + ], + "format": "uint64", + "minimum": 0.0 }, - "bucket": { - "type": "string" + "store_admission_scan_limit": { + "description": "Queued store items one admission pass looks at past work that cannot start yet. Work beyond it waits for the next pass. Must be positive. Defaults to 1024.", + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 }, - "endpoint": { - "default": null, + "store_max_flush_staging": { + "description": "Partition filesystem flushes one partition maintainer lets stage at once. Staging writes the flush's records into the store. Must be positive. Defaults to 1.", "type": [ - "string", + "integer", "null" - ] + ], + "format": "uint32", + "minimum": 0.0 }, - "prefix": { - "default": null, + "store_max_flush_uploads": { + "description": "Partition filesystem flushes one partition maintainer keeps in flight at once, staging or uploading; a staging flush counts because it uploads next. Must be at least `store_max_flush_staging`. Defaults to 2.", "type": [ - "string", + "integer", "null" - ] + ], + "format": "uint32", + "minimum": 0.0 }, - "region": { - "default": null, + "store_max_keyed_in_flight": { + "description": "Filesystem applies and loads one partition maintainer admits to its store at once. They run concurrently, one task each, and their replica reads stay bounded by the cold byte budget, so the cap sizes concurrency for a burst of volume creates rather than memory. Must be positive. Defaults to 256.", "type": [ - "string", + "integer", "null" - ] + ], + "format": "uint32", + "minimum": 0.0 }, - "secret_access_key": { - "default": null, + "store_volume_lock_stripes": { + "description": "Volume lock stripes of each partition filesystem store. Two volumes on one stripe serialize their store work. Must be positive. Defaults to 1024.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "store_volume_locks": { + "description": "Which store work takes volume stripes. `core` (the default) trusts the maintainer core to order applies, loads, session opens, lifecycle lookups and the flush retention publish, so they take only the partition lock; stripes then guard only checkpoint-session opens against hold releases, checkpoint deletions and sweeps. `stripes` keeps a stripe on every operation, as before.", "anyOf": [ { - "$ref": "#/definitions/Secret" + "$ref": "#/definitions/StoreVolumeLocks" }, { "type": "null" } ] + }, + "volume_client": { + "default": { + "close_after_idle_ms": null, + "max_loaded_volumes": null, + "max_requests": null, + "max_volume_key_bytes": null, + "open_timeout_ms": null, + "payload_codec": null, + "sweep_interval_ms": null + }, + "allOf": [ + { + "$ref": "#/definitions/VolumeClientConfig" + } + ] + }, + "volume_request_capacity": { + "description": "Per-subject lifecycle request capacity, isolated from other UPS traffic. Defaults to 1024.", + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, + "volume_request_timeout_ms": { + "description": "Entire lifecycle RPC budget, including route refreshes. Defaults to five seconds.", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "write_to_cold_above_bytes": { + "description": "Committed suffix threshold, default 64 MiB and maximum 256 MiB.", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "write_to_cold_after_ms": { + "description": "Cold-write age from the first unflushed entry, plus up to a tenth of it as jitter. Defaults to one minute. Storage workers require the age with its jitter to stay below `stop_timeout_ms`, so a stopping worker never waits on a slower tiering cadence than its own stop budget.", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 } }, "additionalProperties": false }, - "Secret": { - "type": "string" - }, "StoreVolumeLocks": { - "description": "Which tablet store operations take volume lock stripes.", + "description": "Which partition store operations take volume lock stripes.", "oneOf": [ { "description": "Only work the maintainer core does not order takes a stripe.", @@ -3129,45 +3294,6 @@ }, "additionalProperties": false }, - "TabletBalancingConfig": { - "description": "Static tablet placement policy; membership and lease timings remain topology-owned.", - "type": "object", - "properties": { - "destination_stability_ms": { - "description": "How long a new worker must be listed in discovery, and pass one disk probe, before the coordinator places tablets on it. Must exceed the topology worker lease plus one renewal and the takeover grace, about 35 s, so a worker that crashes soon after it first appears has left discovery before it qualifies. Startup refuses a shorter value.", - "default": 60000, - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "enabled": { - "description": "Whether the tablet coordinator places, splits and replaces tablets on its own. When disabled, the layout changes only through operator commands: a new cluster gets no first tablet until an operator creates one, and a missing worker is never replaced.", - "default": true, - "type": "boolean" - }, - "max_disk_probes": { - "description": "Maximum concurrent disk admission requests made by the tablet coordinator.", - "default": 4, - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "missing_worker_ms": { - "description": "How long an assigned worker must be missing from discovery before its replicas are replaced. Counted from when discovery drops it, which is itself one lease after its last renewal.", - "default": 120000, - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "tablets_per_core": { - "default": 2, - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - }, - "additionalProperties": false - }, "Telemetry": { "type": "object", "required": [ diff --git a/vendor/docs/examples/docs/actors-quickstart-next-js/registry.ts b/vendor/docs/examples/docs/actors-quickstart-next-js/registry.ts deleted file mode 100644 index 4afe732a..00000000 --- a/vendor/docs/examples/docs/actors-quickstart-next-js/registry.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { actor, setup } from "rivetkit"; - -export const counter = actor({ - state: { count: 0 }, - actions: { - increment: (c, x: number) => { - c.state.count += x; - c.broadcast("newCount", c.state.count); - return c.state.count; - }, - }, -}); - -export const registry = setup({ - use: { counter }, -}); diff --git a/vendor/docs/examples/docs/actors-quickstart-react/index.ts b/vendor/docs/examples/docs/actors-quickstart-react/backend/index.ts similarity index 100% rename from vendor/docs/examples/docs/actors-quickstart-react/index.ts rename to vendor/docs/examples/docs/actors-quickstart-react/backend/index.ts diff --git a/vendor/docs/examples/docs/actors-quickstart-react/Counter.tsx b/vendor/docs/examples/docs/actors-quickstart-react/frontend/Counter.tsx similarity index 85% rename from vendor/docs/examples/docs/actors-quickstart-react/Counter.tsx rename to vendor/docs/examples/docs/actors-quickstart-react/frontend/Counter.tsx index a62ee024..26aa5be7 100644 --- a/vendor/docs/examples/docs/actors-quickstart-react/Counter.tsx +++ b/vendor/docs/examples/docs/actors-quickstart-react/frontend/Counter.tsx @@ -1,16 +1,16 @@ import { createRivetKit } from "@rivetkit/react"; import { useState } from "react"; -import type { registry } from "./index"; +import type { registry } from "../backend/index"; const { useActor } = createRivetKit("http://localhost:6420"); -function Counter() { +export function Counter() { const [count, setCount] = useState(0); // Get or create a counter actor for the key "my-counter" const counter = useActor({ name: "counter", - key: ["my-counter"] + key: ["my-counter"], }); // Listen to realtime events diff --git a/vendor/docs/examples/docs/actors-quickstart-react/frontend/main.tsx b/vendor/docs/examples/docs/actors-quickstart-react/frontend/main.tsx new file mode 100644 index 00000000..a8e4ea9d --- /dev/null +++ b/vendor/docs/examples/docs/actors-quickstart-react/frontend/main.tsx @@ -0,0 +1,9 @@ +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import { Counter } from "./Counter"; + +createRoot(document.getElementById("root")!).render( + + + , +); diff --git a/vendor/docs/examples/docs/actors-versions/programmatic-version.ts b/vendor/docs/examples/docs/actors-versions/programmatic-version.ts deleted file mode 100644 index 9763d971..00000000 --- a/vendor/docs/examples/docs/actors-versions/programmatic-version.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { actor, setup } from "rivetkit"; - -const myActor = actor({ state: {}, actions: {} }); - -const registry = setup({ - use: { myActor }, - envoy: { - version: 2, - }, -}); diff --git a/vendor/docs/examples/docs/api/actors-destroy.ts b/vendor/docs/examples/docs/api/actors-destroy.ts index 7718ad8c..d76fa102 100644 --- a/vendor/docs/examples/docs/api/actors-destroy.ts +++ b/vendor/docs/examples/docs/api/actors-destroy.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; const actorId = "00000000-0000-0000-0000-000000000000"; diff --git a/vendor/docs/examples/docs/api/actors-list-names.ts b/vendor/docs/examples/docs/api/actors-list-names.ts index ce5f865f..19ca05e2 100644 --- a/vendor/docs/examples/docs/api/actors-list-names.ts +++ b/vendor/docs/examples/docs/api/actors-list-names.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; diff --git a/vendor/docs/examples/docs/api/actors-list.ts b/vendor/docs/examples/docs/api/actors-list.ts index fcca97ee..55a79fcb 100644 --- a/vendor/docs/examples/docs/api/actors-list.ts +++ b/vendor/docs/examples/docs/api/actors-list.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; diff --git a/vendor/docs/examples/docs/api/actors-reschedule.ts b/vendor/docs/examples/docs/api/actors-reschedule.ts index 3a2f9b23..3bb1a563 100644 --- a/vendor/docs/examples/docs/api/actors-reschedule.ts +++ b/vendor/docs/examples/docs/api/actors-reschedule.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; const actorId = "00000000-0000-0000-0000-000000000000"; diff --git a/vendor/docs/examples/docs/api/actors-sleep.ts b/vendor/docs/examples/docs/api/actors-sleep.ts index e1232b21..a1d07784 100644 --- a/vendor/docs/examples/docs/api/actors-sleep.ts +++ b/vendor/docs/examples/docs/api/actors-sleep.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; const actorId = "00000000-0000-0000-0000-000000000000"; diff --git a/vendor/docs/examples/docs/api/connection-actions.ts b/vendor/docs/examples/docs/api/connection-actions.ts index d90ec127..3de81cd1 100644 --- a/vendor/docs/examples/docs/api/connection-actions.ts +++ b/vendor/docs/examples/docs/api/connection-actions.ts @@ -1,5 +1,5 @@ const ws = new WebSocket( - `wss://rivet.example.com/gateway/${process.env.ACTOR_ID}/connect`, + `wss://api.rivet.dev/gateway/${process.env.ACTOR_ID}/connect`, ["rivet", "rivet_encoding.json", `rivet_token.${process.env.RIVET_TOKEN}`], ); diff --git a/vendor/docs/examples/docs/api/connection-connect.ts b/vendor/docs/examples/docs/api/connection-connect.ts index ee4bf891..88e74ed3 100644 --- a/vendor/docs/examples/docs/api/connection-connect.ts +++ b/vendor/docs/examples/docs/api/connection-connect.ts @@ -1,7 +1,7 @@ // Open a connection by actor name. The selector query parameters are the same // ones used by the HTTP endpoints; the token and encoding travel as // WebSocket subprotocols because browsers cannot set headers on an upgrade. -const url = new URL("wss://rivet.example.com/gateway/counter/connect"); +const url = new URL("wss://api.rivet.dev/gateway/counter/connect"); url.searchParams.set("rvt-namespace", process.env.RIVET_NAMESPACE!); url.searchParams.set("rvt-method", "getOrCreate"); url.searchParams.set("rvt-key", "my-counter"); diff --git a/vendor/docs/examples/docs/api/connection-errors.ts b/vendor/docs/examples/docs/api/connection-errors.ts index f8e796c7..6345825a 100644 --- a/vendor/docs/examples/docs/api/connection-errors.ts +++ b/vendor/docs/examples/docs/api/connection-errors.ts @@ -1,5 +1,5 @@ const ws = new WebSocket( - `wss://rivet.example.com/gateway/${process.env.ACTOR_ID}/connect`, + `wss://api.rivet.dev/gateway/${process.env.ACTOR_ID}/connect`, ["rivet", "rivet_encoding.json", `rivet_token.${process.env.RIVET_TOKEN}`], ); diff --git a/vendor/docs/examples/docs/api/connection-events.ts b/vendor/docs/examples/docs/api/connection-events.ts index 71ad178a..7e85c61b 100644 --- a/vendor/docs/examples/docs/api/connection-events.ts +++ b/vendor/docs/examples/docs/api/connection-events.ts @@ -1,5 +1,5 @@ const ws = new WebSocket( - `wss://rivet.example.com/gateway/${process.env.ACTOR_ID}/connect`, + `wss://api.rivet.dev/gateway/${process.env.ACTOR_ID}/connect`, ["rivet", "rivet_encoding.json", `rivet_token.${process.env.RIVET_TOKEN}`], ); diff --git a/vendor/docs/examples/docs/api/control-plane-datacenters.ts b/vendor/docs/examples/docs/api/control-plane-datacenters.ts index 6f14c5eb..d5afca6c 100644 --- a/vendor/docs/examples/docs/api/control-plane-datacenters.ts +++ b/vendor/docs/examples/docs/api/control-plane-datacenters.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const token = process.env.RIVET_TOKEN ?? ""; const response = await fetch(`${endpoint}/datacenters`, { diff --git a/vendor/docs/examples/docs/api/control-plane-metadata.ts b/vendor/docs/examples/docs/api/control-plane-metadata.ts index ea784880..43300b91 100644 --- a/vendor/docs/examples/docs/api/control-plane-metadata.ts +++ b/vendor/docs/examples/docs/api/control-plane-metadata.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const response = await fetch(`${endpoint}/metadata`); const metadata = await response.json(); diff --git a/vendor/docs/examples/docs/api/gateway-metadata.ts b/vendor/docs/examples/docs/api/gateway-metadata.ts index 95da90f4..d677d2dd 100644 --- a/vendor/docs/examples/docs/api/gateway-metadata.ts +++ b/vendor/docs/examples/docs/api/gateway-metadata.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const response = await fetch( `${endpoint}/gateway/${process.env.ACTOR_ID}/metadata`, { diff --git a/vendor/docs/examples/docs/api/gateway-queue.ts b/vendor/docs/examples/docs/api/gateway-queue.ts index 73f95114..8d6a2aa6 100644 --- a/vendor/docs/examples/docs/api/gateway-queue.ts +++ b/vendor/docs/examples/docs/api/gateway-queue.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const actorId = process.env.ACTOR_ID; const response = await fetch(`${endpoint}/gateway/${actorId}/queue/increment`, { method: "POST", diff --git a/vendor/docs/examples/docs/api/inspector-action.ts b/vendor/docs/examples/docs/api/inspector-action.ts deleted file mode 100644 index ac8aca2c..00000000 --- a/vendor/docs/examples/docs/api/inspector-action.ts +++ /dev/null @@ -1,14 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/action/increment`, - { - method: "POST", - headers: { - Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ args: [1] }), - }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-connections.ts b/vendor/docs/examples/docs/api/inspector-connections.ts deleted file mode 100644 index cebb890d..00000000 --- a/vendor/docs/examples/docs/api/inspector-connections.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/connections`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-database-execute.ts b/vendor/docs/examples/docs/api/inspector-database-execute.ts deleted file mode 100644 index 0786a92e..00000000 --- a/vendor/docs/examples/docs/api/inspector-database-execute.ts +++ /dev/null @@ -1,17 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/database/execute`, - { - method: "POST", - headers: { - Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ - sql: "SELECT * FROM users WHERE id = ?", - args: ["user-123"], - }), - }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-database-rows.ts b/vendor/docs/examples/docs/api/inspector-database-rows.ts deleted file mode 100644 index a21e1be3..00000000 --- a/vendor/docs/examples/docs/api/inspector-database-rows.ts +++ /dev/null @@ -1,12 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const query = new URLSearchParams({ - table: "users", - limit: "100", - offset: "0", -}); -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/database/rows?${query}`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-database-schema.ts b/vendor/docs/examples/docs/api/inspector-database-schema.ts deleted file mode 100644 index e6d5acdc..00000000 --- a/vendor/docs/examples/docs/api/inspector-database-schema.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/database/schema`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-queue-delete.ts b/vendor/docs/examples/docs/api/inspector-queue-delete.ts deleted file mode 100644 index 748c1b4c..00000000 --- a/vendor/docs/examples/docs/api/inspector-queue-delete.ts +++ /dev/null @@ -1,10 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/queue`, - { - method: "DELETE", - headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` }, - }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-queue-get.ts b/vendor/docs/examples/docs/api/inspector-queue-get.ts deleted file mode 100644 index a55ec407..00000000 --- a/vendor/docs/examples/docs/api/inspector-queue-get.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/queue?limit=50`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-queue-post.ts b/vendor/docs/examples/docs/api/inspector-queue-post.ts deleted file mode 100644 index d5c71989..00000000 --- a/vendor/docs/examples/docs/api/inspector-queue-post.ts +++ /dev/null @@ -1,14 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/queue`, - { - method: "POST", - headers: { - Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ name: "increment", body: { amount: 1 } }), - }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-rpcs.ts b/vendor/docs/examples/docs/api/inspector-rpcs.ts deleted file mode 100644 index 356e615e..00000000 --- a/vendor/docs/examples/docs/api/inspector-rpcs.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/rpcs`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-state-get.ts b/vendor/docs/examples/docs/api/inspector-state-get.ts deleted file mode 100644 index 783deb57..00000000 --- a/vendor/docs/examples/docs/api/inspector-state-get.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/state`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-state-patch.ts b/vendor/docs/examples/docs/api/inspector-state-patch.ts deleted file mode 100644 index 36ef34dc..00000000 --- a/vendor/docs/examples/docs/api/inspector-state-patch.ts +++ /dev/null @@ -1,14 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/state`, - { - method: "PATCH", - headers: { - Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ state: { count: 2 } }), - }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-summary.ts b/vendor/docs/examples/docs/api/inspector-summary.ts deleted file mode 100644 index 37f0f793..00000000 --- a/vendor/docs/examples/docs/api/inspector-summary.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/summary`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-traces.ts b/vendor/docs/examples/docs/api/inspector-traces.ts deleted file mode 100644 index 9a3c1a62..00000000 --- a/vendor/docs/examples/docs/api/inspector-traces.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/traces?startMs=0&limit=100`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-workflow-history.ts b/vendor/docs/examples/docs/api/inspector-workflow-history.ts deleted file mode 100644 index 64d289d0..00000000 --- a/vendor/docs/examples/docs/api/inspector-workflow-history.ts +++ /dev/null @@ -1,7 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/workflow-history`, - { headers: { Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}` } }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/inspector-workflow-replay.ts b/vendor/docs/examples/docs/api/inspector-workflow-replay.ts deleted file mode 100644 index 3bf3cdc8..00000000 --- a/vendor/docs/examples/docs/api/inspector-workflow-replay.ts +++ /dev/null @@ -1,14 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const response = await fetch( - `${endpoint}/gateway/${process.env.ACTOR_ID}/inspector/workflow/replay`, - { - method: "POST", - headers: { - Authorization: `Bearer ${process.env.INSPECTOR_TOKEN}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ entryId: "entry-123" }), - }, -); -console.log(await response.json()); -export {}; diff --git a/vendor/docs/examples/docs/api/namespaces-create.ts b/vendor/docs/examples/docs/api/namespaces-create.ts index c2f92ff5..3bda46bc 100644 --- a/vendor/docs/examples/docs/api/namespaces-create.ts +++ b/vendor/docs/examples/docs/api/namespaces-create.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const token = process.env.RIVET_TOKEN ?? ""; const response = await fetch(`${endpoint}/namespaces`, { diff --git a/vendor/docs/examples/docs/api/namespaces-list.ts b/vendor/docs/examples/docs/api/namespaces-list.ts index 5b598685..34700884 100644 --- a/vendor/docs/examples/docs/api/namespaces-list.ts +++ b/vendor/docs/examples/docs/api/namespaces-list.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const token = process.env.RIVET_TOKEN ?? ""; const response = await fetch(`${endpoint}/namespaces`, { diff --git a/vendor/docs/examples/docs/api/pools-delete.ts b/vendor/docs/examples/docs/api/pools-delete.ts new file mode 100644 index 00000000..ad9c5134 --- /dev/null +++ b/vendor/docs/examples/docs/api/pools-delete.ts @@ -0,0 +1,16 @@ +const endpoint = "https://api.rivet.dev"; +const namespace = process.env.RIVET_NAMESPACE ?? "default"; +const token = process.env.RIVET_TOKEN ?? ""; +const pool = process.env.RIVET_POOL ?? "default"; + +const params = new URLSearchParams({ namespace }); +const response = await fetch( + `${endpoint}/pools/${encodeURIComponent(pool)}?${params}`, + { + method: "DELETE", + headers: { Authorization: `Bearer ${token}` }, + }, +); +console.log(response.status); + +export {}; diff --git a/vendor/docs/examples/docs/api/pools-get.ts b/vendor/docs/examples/docs/api/pools-get.ts new file mode 100644 index 00000000..852a5f71 --- /dev/null +++ b/vendor/docs/examples/docs/api/pools-get.ts @@ -0,0 +1,13 @@ +const endpoint = "https://api.rivet.dev"; +const namespace = process.env.RIVET_NAMESPACE ?? "default"; +const token = process.env.RIVET_TOKEN ?? ""; +const pool = process.env.RIVET_POOL ?? "default"; + +const params = new URLSearchParams({ namespace }); +const response = await fetch( + `${endpoint}/pools/${encodeURIComponent(pool)}?${params}`, + { headers: { Authorization: `Bearer ${token}` } }, +); +console.log(await response.json()); + +export {}; diff --git a/vendor/docs/examples/docs/api/pools-list-nodes.ts b/vendor/docs/examples/docs/api/pools-list-nodes.ts new file mode 100644 index 00000000..b55c107f --- /dev/null +++ b/vendor/docs/examples/docs/api/pools-list-nodes.ts @@ -0,0 +1,14 @@ +const endpoint = "https://api.rivet.dev"; +const namespace = process.env.RIVET_NAMESPACE ?? "default"; +const token = process.env.RIVET_TOKEN ?? ""; +const pool = process.env.RIVET_POOL ?? "default"; + +const params = new URLSearchParams({ namespace }); +const response = await fetch( + `${endpoint}/pools/${encodeURIComponent(pool)}/nodes?${params}`, + { headers: { Authorization: `Bearer ${token}` } }, +); +const { nodes, pagination } = await response.json(); +console.log(nodes, pagination.cursor); + +export {}; diff --git a/vendor/docs/examples/docs/api/workers-configs-list.ts b/vendor/docs/examples/docs/api/pools-list.ts similarity index 52% rename from vendor/docs/examples/docs/api/workers-configs-list.ts rename to vendor/docs/examples/docs/api/pools-list.ts index 1f1c8521..eac08588 100644 --- a/vendor/docs/examples/docs/api/workers-configs-list.ts +++ b/vendor/docs/examples/docs/api/pools-list.ts @@ -1,12 +1,12 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; const params = new URLSearchParams({ namespace }); -const response = await fetch(`${endpoint}/runner-configs?${params}`, { +const response = await fetch(`${endpoint}/pools?${params}`, { headers: { Authorization: `Bearer ${token}` }, }); -const { runner_configs } = await response.json(); -console.log(runner_configs); +const { pools, pagination } = await response.json(); +console.log(pools, pagination.cursor); export {}; diff --git a/vendor/docs/examples/docs/api/workers-configs-upsert.ts b/vendor/docs/examples/docs/api/pools-upsert.ts similarity index 59% rename from vendor/docs/examples/docs/api/workers-configs-upsert.ts rename to vendor/docs/examples/docs/api/pools-upsert.ts index 50a37d3d..0097c1c7 100644 --- a/vendor/docs/examples/docs/api/workers-configs-upsert.ts +++ b/vendor/docs/examples/docs/api/pools-upsert.ts @@ -1,18 +1,18 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; -const workerName = process.env.RUNNER_NAME ?? "default"; +const pool = process.env.RIVET_POOL ?? "default"; const params = new URLSearchParams({ namespace }); const response = await fetch( - `${endpoint}/runner-configs/${encodeURIComponent(workerName)}?${params}`, + `${endpoint}/pools/${encodeURIComponent(pool)}?${params}`, { method: "PUT", headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", }, - body: JSON.stringify({ datacenters: { local: { normal: {} } } }), + body: JSON.stringify({ drain_on_version_upgrade: true }), }, ); console.log(await response.json()); diff --git a/vendor/docs/examples/docs/api/tokens-inspect.ts b/vendor/docs/examples/docs/api/tokens-inspect.ts index c562d121..7573b89f 100644 --- a/vendor/docs/examples/docs/api/tokens-inspect.ts +++ b/vendor/docs/examples/docs/api/tokens-inspect.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const token = process.env.RIVET_TOKEN ?? ""; // Inspect reports on the token used to authenticate the request itself. diff --git a/vendor/docs/examples/docs/api/workers-configs-delete.ts b/vendor/docs/examples/docs/api/workers-configs-delete.ts deleted file mode 100644 index cdc01d9e..00000000 --- a/vendor/docs/examples/docs/api/workers-configs-delete.ts +++ /dev/null @@ -1,13 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const namespace = process.env.RIVET_NAMESPACE ?? "default"; -const token = process.env.RIVET_TOKEN ?? ""; -const workerName = process.env.RUNNER_NAME ?? "default"; - -const params = new URLSearchParams({ namespace }); -const response = await fetch( - `${endpoint}/runner-configs/${encodeURIComponent(workerName)}?${params}`, - { method: "DELETE", headers: { Authorization: `Bearer ${token}` } }, -); -console.log(response.ok); - -export {}; diff --git a/vendor/docs/examples/docs/api/workers-configs-refresh-metadata.ts b/vendor/docs/examples/docs/api/workers-configs-refresh-metadata.ts index 337d7c97..1f1a7c02 100644 --- a/vendor/docs/examples/docs/api/workers-configs-refresh-metadata.ts +++ b/vendor/docs/examples/docs/api/workers-configs-refresh-metadata.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; const workerName = process.env.RUNNER_NAME ?? "default"; diff --git a/vendor/docs/examples/docs/api/workers-list.ts b/vendor/docs/examples/docs/api/workers-list.ts deleted file mode 100644 index 06f1d56e..00000000 --- a/vendor/docs/examples/docs/api/workers-list.ts +++ /dev/null @@ -1,12 +0,0 @@ -const endpoint = "https://rivet.example.com"; -const namespace = process.env.RIVET_NAMESPACE ?? "default"; -const token = process.env.RIVET_TOKEN ?? ""; - -const params = new URLSearchParams({ namespace }); -const response = await fetch(`${endpoint}/envoys?${params}`, { - headers: { Authorization: `Bearer ${token}` }, -}); -const { envoys: workers, pagination } = await response.json(); -console.log(workers, pagination.cursor); - -export {}; diff --git a/vendor/docs/examples/docs/api/workers-serverless-health-check.ts b/vendor/docs/examples/docs/api/workers-serverless-health-check.ts index 860536f6..c6e0c54f 100644 --- a/vendor/docs/examples/docs/api/workers-serverless-health-check.ts +++ b/vendor/docs/examples/docs/api/workers-serverless-health-check.ts @@ -1,4 +1,4 @@ -const endpoint = "https://rivet.example.com"; +const endpoint = "https://api.rivet.dev"; const namespace = process.env.RIVET_NAMESPACE ?? "default"; const token = process.env.RIVET_TOKEN ?? ""; diff --git a/vendor/docs/examples/docs/cookbook-cron-jobs/daily-report.ts b/vendor/docs/examples/docs/cookbook-cron-jobs/daily-report.ts deleted file mode 100644 index c434d36c..00000000 --- a/vendor/docs/examples/docs/cookbook-cron-jobs/daily-report.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { actor } from "rivetkit"; - -export const dailyReport = actor({ - state: { lastRunAt: 0 }, - onCreate: async (c) => { - await c.cron.set({ - name: "daily-report", - expression: "0 9 * * *", - action: "runReport", - }); - }, - actions: { - runReport: (c) => { - // Do the job's work, then record the run. - c.state.lastRunAt = Date.now(); - }, - }, -}); diff --git a/vendor/docs/examples/docs/durable-streams/client.ts b/vendor/docs/examples/docs/durable-streams/client.ts new file mode 100644 index 00000000..97fdedf0 --- /dev/null +++ b/vendor/docs/examples/docs/durable-streams/client.ts @@ -0,0 +1,14 @@ +import { DurableStream } from "@durable-streams/client"; + +const stream = await DurableStream.create({ + url: "http://127.0.0.1:8642/durable-streams/v1/stream/demo", + contentType: "application/json", +}); + +await stream.append(JSON.stringify({ message: "hello" })); + +// Read from the beginning, then keep receiving new messages live +const res = await stream.stream<{ message: string }>(); +res.subscribeJson(async (batch) => { + for (const item of batch.items) console.log(item.message); +}); diff --git a/vendor/docs/examples/docs/durable-streams/create.ts b/vendor/docs/examples/docs/durable-streams/create.ts new file mode 100644 index 00000000..582ec8f2 --- /dev/null +++ b/vendor/docs/examples/docs/durable-streams/create.ts @@ -0,0 +1,11 @@ +import { DurableStream } from "@durable-streams/client"; + +// One stream per chat session +const stream = await DurableStream.create({ + url: "http://127.0.0.1:8642/durable-streams/v1/stream/chat/session-1", + contentType: "application/json", + // Delete the stream after a day with no reads or writes + ttlSeconds: 86400, +}); + +console.log("created", stream.url); diff --git a/vendor/docs/examples/docs/durable-streams/producer.ts b/vendor/docs/examples/docs/durable-streams/producer.ts new file mode 100644 index 00000000..eb2f8a16 --- /dev/null +++ b/vendor/docs/examples/docs/durable-streams/producer.ts @@ -0,0 +1,21 @@ +import { DurableStream, IdempotentProducer } from "@durable-streams/client"; + +const stream = new DurableStream({ + url: "http://127.0.0.1:8642/durable-streams/v1/stream/chat/session-1", + contentType: "application/json", +}); + +// Keep the producer ID the same across restarts. With autoClaim, a restarted +// agent takes over and the old one can no longer write. +const producer = new IdempotentProducer(stream, "agent-session-1", { + autoClaim: true, + onError: (error) => console.error("append failed", error), +}); + +for (const token of ["It's", " sunny", " today"]) { + producer.append(JSON.stringify({ token })); +} + +// Wait until every token is stored, then close the stream +await producer.flush(); +await producer.close(); diff --git a/vendor/docs/examples/docs/durable-streams/read-history.ts b/vendor/docs/examples/docs/durable-streams/read-history.ts new file mode 100644 index 00000000..457570d7 --- /dev/null +++ b/vendor/docs/examples/docs/durable-streams/read-history.ts @@ -0,0 +1,10 @@ +import { stream } from "@durable-streams/client"; + +const url = "http://127.0.0.1:8642/durable-streams/v1/stream/chat/session-1"; + +// Everything written so far, then stop +const res = await stream<{ token: string }>({ url, offset: "-1", live: false }); +const messages = await res.json(); + +console.log(messages); +console.log("read from here next:", res.offset); diff --git a/vendor/docs/examples/docs/durable-streams/read-live.ts b/vendor/docs/examples/docs/durable-streams/read-live.ts new file mode 100644 index 00000000..362854f3 --- /dev/null +++ b/vendor/docs/examples/docs/durable-streams/read-live.ts @@ -0,0 +1,14 @@ +import { stream } from "@durable-streams/client"; + +const url = "http://127.0.0.1:8642/durable-streams/v1/stream/chat/session-1"; + +// "-1" starts at the beginning. Pass a saved offset to pick up where you left off. +const savedOffset: string = "-1"; + +const res = await stream<{ token: string }>({ url, offset: savedOffset, live: "sse" }); +res.subscribeJson(async (batch) => { + for (const item of batch.items) console.log(item.token); + + // Save this to resume from the same place after a refresh + console.log("offset", batch.offset); +}); diff --git a/vendor/docs/examples/docs/durable-streams/write.ts b/vendor/docs/examples/docs/durable-streams/write.ts new file mode 100644 index 00000000..c68ab7ce --- /dev/null +++ b/vendor/docs/examples/docs/durable-streams/write.ts @@ -0,0 +1,13 @@ +import { DurableStream } from "@durable-streams/client"; + +const stream = new DurableStream({ + url: "http://127.0.0.1:8642/durable-streams/v1/stream/chat/session-1", + contentType: "application/json", +}); + +// Each append is one message +await stream.append(JSON.stringify({ token: "It's" })); +await stream.append(JSON.stringify({ token: " sunny" })); + +// Close with a final message: readers know the reply is complete +await stream.close({ body: JSON.stringify({ token: "." }) }); diff --git a/vendor/docs/examples/docs/general-edge/client.ts b/vendor/docs/examples/docs/general-edge/client.ts new file mode 100644 index 00000000..fde898f5 --- /dev/null +++ b/vendor/docs/examples/docs/general-edge/client.ts @@ -0,0 +1,12 @@ +import { createClient } from "rivetkit/client"; +import { actor, setup } from "rivetkit"; + +const example = actor({ state: {}, actions: {} }); +const registry = setup({ use: { example } }); + +const client = createClient("http://localhost:6420"); + +// Create actor in a specific region using getOrCreate +const actorHandle = client.example.getOrCreate(["my-actor"], { + createInRegion: "atl" +}); diff --git a/vendor/docs/examples/docs/general-jwt/quickstart/client.ts b/vendor/docs/examples/docs/general-jwt/quickstart/client.ts index bf78e5d5..49cbb1ed 100644 --- a/vendor/docs/examples/docs/general-jwt/quickstart/client.ts +++ b/vendor/docs/examples/docs/general-jwt/quickstart/client.ts @@ -14,7 +14,7 @@ async function fetchToken(): Promise<{ actorId: string; token: string }> { const { actorId } = await fetchToken(); const client = createClient({ - endpoint: "https://my-namespace@rivet.example.com", + endpoint: "https://rivet.example.com", namespace: "production", // Called whenever RivetKit needs a credential, including after one expires. diff --git a/vendor/docs/examples/docs/onboarding-actors/client.ts b/vendor/docs/examples/docs/onboarding-actors/client.ts new file mode 100644 index 00000000..307c6365 --- /dev/null +++ b/vendor/docs/examples/docs/onboarding-actors/client.ts @@ -0,0 +1,20 @@ +import { createClient } from "rivetkit/client"; +import type { registry } from "./index"; + +// Connect to the server from index.ts. The registry type checks every call. +const client = createClient("http://localhost:6420"); + +// Get the room keyed "general", creating it on first use. +const room = client.chatRoom.getOrCreate(["general"]); + +// Open a realtime connection and print each message as it arrives. +const connection = room.connect(); +connection.on("newMessage", (message: { sender: string; text: string }) => { + console.log(`${message.sender}: ${message.text}`); +}); + +// Send a message. The Actor saves it to SQLite before broadcasting it. +await connection.sendMessage("alice", "Hello, Rivet!"); + +// The history is still there after the Actor sleeps or restarts. +console.log(await room.getHistory()); diff --git a/vendor/docs/examples/docs/onboarding-actors/index.ts b/vendor/docs/examples/docs/onboarding-actors/index.ts new file mode 100644 index 00000000..0cf38744 --- /dev/null +++ b/vendor/docs/examples/docs/onboarding-actors/index.ts @@ -0,0 +1,43 @@ +import { actor, setup } from "rivetkit"; +import { db } from "rivetkit/db"; + +// A chat room Actor. Every room key gets its own instance with its own SQLite +// database, which survives restarts and redeploys. +export const chatRoom = actor({ + // Create the messages table the first time a room starts. + db: db({ + onMigrate: async (db) => { + await db.execute(` + CREATE TABLE IF NOT EXISTS messages ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + sender TEXT NOT NULL, + text TEXT NOT NULL + ) + `); + }, + }), + + actions: { + // Save a message, then push it to everyone connected to this room. + sendMessage: async (c, sender: string, text: string) => { + await c.db.execute( + "INSERT INTO messages (sender, text) VALUES (?, ?)", + sender, + text, + ); + + c.broadcast("newMessage", { sender, text }); + }, + + // Read the room's history, oldest first. + getHistory: async (c) => { + return (await c.db.execute( + "SELECT sender, text FROM messages ORDER BY id", + )) as { sender: string; text: string }[]; + }, + }, +}); + +// Register the Actor and start serving it on http://localhost:6420. +export const registry = setup({ use: { chatRoom } }); +registry.start(); diff --git a/vendor/docs/examples/docs/package.json b/vendor/docs/examples/docs/package.json index a0e98db3..3ddcea78 100644 --- a/vendor/docs/examples/docs/package.json +++ b/vendor/docs/examples/docs/package.json @@ -1,4 +1,5 @@ { + "license": "MIT", "name": "docs-snippets", "version": "2.0.21", "private": true, @@ -11,10 +12,7 @@ "rivetkit": "workspace:*", "@rivetkit/react": "workspace:*", "@rivetkit/engine-api-full": "workspace:*", - "@rivetkit/next-js": "workspace:*", - "@rivetkit/cloudflare-workers": "workspace:*", "@rivetkit/rivetkit-wasm": "workspace:*", - "@rivetkit/supabase": "workspace:*", "@rivetkit/effect": "workspace:*", "effect": "4.0.0", "@effect/platform-node": "4.0.0", diff --git a/vendor/docs/examples/docs/tsconfig.json b/vendor/docs/examples/docs/tsconfig.json index 498e3a9a..ee88fd1d 100644 --- a/vendor/docs/examples/docs/tsconfig.json +++ b/vendor/docs/examples/docs/tsconfig.json @@ -13,5 +13,12 @@ "jsx": "react-jsx" }, "include": ["**/*.ts", "**/*.tsx"], - "exclude": ["node_modules"] + "exclude": [ + "node_modules", + "actors-quickstart-next-js", + "general-http-server/elysia-handler.ts", + "general-http-server/hono-handler.ts", + "general-http-server/serve.ts", + "actors-actions/calling-backend.ts" + ] }