diff --git a/rivetkit-rust/packages/rivetkit-core/src/registry/envoy_callbacks.rs b/rivetkit-rust/packages/rivetkit-core/src/registry/envoy_callbacks.rs index 07985e6f07..64f823f940 100644 --- a/rivetkit-rust/packages/rivetkit-core/src/registry/envoy_callbacks.rs +++ b/rivetkit-rust/packages/rivetkit-core/src/registry/envoy_callbacks.rs @@ -197,7 +197,6 @@ impl ServeConfig { serverless_validate_endpoint: settings.serverless_validate_endpoint, serverless_max_start_payload_bytes: settings.serverless_max_start_payload_bytes, serverless_cache_envoy: true, - force_normal_runner_config_upsert: false, } } } diff --git a/rivetkit-rust/packages/rivetkit-core/src/registry/mod.rs b/rivetkit-rust/packages/rivetkit-core/src/registry/mod.rs index a045c0b8f2..805580265a 100644 --- a/rivetkit-rust/packages/rivetkit-core/src/registry/mod.rs +++ b/rivetkit-rust/packages/rivetkit-core/src/registry/mod.rs @@ -216,10 +216,6 @@ pub struct ServeConfig { pub serverless_validate_endpoint: bool, pub serverless_max_start_payload_bytes: usize, pub serverless_cache_envoy: bool, - /// When true, upsert a normal runner config to the engine on startup - /// even if the endpoint is not a local engine. Set by the TS Registry - /// when `RIVETKIT_RUNTIME_MODE` resolves to `envoy`. - pub force_normal_runner_config_upsert: bool, } #[derive(Debug, Default, Deserialize)] @@ -505,7 +501,7 @@ impl CoreRegistry { } #[cfg(feature = "native-runtime")] - runner_config::ensure_normal_runner_config(&config).await?; + runner_config::ensure_local_normal_runner_config(&config).await?; let callbacks = Arc::new(RegistryCallbacks { dispatcher: dispatcher.clone(), }); diff --git a/rivetkit-rust/packages/rivetkit-core/src/registry/runner_config.rs b/rivetkit-rust/packages/rivetkit-core/src/registry/runner_config.rs index 340a5545db..88b1480b55 100644 --- a/rivetkit-rust/packages/rivetkit-core/src/registry/runner_config.rs +++ b/rivetkit-rust/packages/rivetkit-core/src/registry/runner_config.rs @@ -17,8 +17,8 @@ struct Datacenter { name: String, } -pub(super) async fn ensure_normal_runner_config(config: &ServeConfig) -> Result<()> { - if !is_local_engine_endpoint(&config.endpoint) && !config.force_normal_runner_config_upsert { +pub(super) async fn ensure_local_normal_runner_config(config: &ServeConfig) -> Result<()> { + if !is_local_engine_endpoint(&config.endpoint) { return Ok(()); } @@ -51,7 +51,7 @@ pub(super) async fn ensure_normal_runner_config(config: &ServeConfig) -> Result< .json(&body) .send() .await - .context("upsert normal runner config")?; + .context("upsert local runner config")?; let status = response.status(); if !status.is_success() { let response_body = response @@ -59,7 +59,7 @@ pub(super) async fn ensure_normal_runner_config(config: &ServeConfig) -> Result< .await .context("read failed runner config response body")?; anyhow::bail!( - "failed to upsert normal runner config `{}`: {} {}", + "failed to upsert local runner config `{}`: {} {}", config.pool_name, status, response_body @@ -69,7 +69,7 @@ pub(super) async fn ensure_normal_runner_config(config: &ServeConfig) -> Result< tracing::debug!( namespace = %config.namespace, pool_name = %config.pool_name, - "ensured normal runner config" + "ensured local normal runner config" ); Ok(()) @@ -80,7 +80,7 @@ async fn get_datacenters(client: &Client, config: &ServeConfig) -> Result Result, pub serverless_validate_endpoint: bool, pub serverless_max_start_payload_bytes: u32, - pub force_normal_runner_config_upsert: Option, } #[napi(object)] @@ -657,9 +656,6 @@ fn serve_config_from_js( serverless_validate_endpoint: config.serverless_validate_endpoint, serverless_max_start_payload_bytes: config.serverless_max_start_payload_bytes as usize, serverless_cache_envoy, - force_normal_runner_config_upsert: config - .force_normal_runner_config_upsert - .unwrap_or(false), } } diff --git a/rivetkit-typescript/packages/rivetkit/src/registry/runtime.ts b/rivetkit-typescript/packages/rivetkit/src/registry/runtime.ts index 8002d3e732..22209a7ada 100644 --- a/rivetkit-typescript/packages/rivetkit/src/registry/runtime.ts +++ b/rivetkit-typescript/packages/rivetkit/src/registry/runtime.ts @@ -1,5 +1,4 @@ import type { SqliteNativeMetrics } from "@/common/database/config"; -import { getRivetkitRuntimeMode } from "@/utils/env-vars"; import type { RegistryConfig } from "./config"; declare const handleBrand: unique symbol; @@ -244,7 +243,6 @@ export interface RuntimeServeConfig { serverlessClientToken?: string; serverlessValidateEndpoint: boolean; serverlessMaxStartPayloadBytes: number; - forceNormalRunnerConfigUpsert?: boolean; } export interface RuntimeListenerConfig { @@ -601,9 +599,6 @@ export async function buildServeConfig( serveConfig.inspectorTestToken = process.env._RIVET_TEST_INSPECTOR_TOKEN ?? "token"; } - if (getRivetkitRuntimeMode() === "envoy") { - serveConfig.forceNormalRunnerConfigUpsert = true; - } return serveConfig; } diff --git a/rivetkit-typescript/packages/rivetkit/src/utils/env-vars.ts b/rivetkit-typescript/packages/rivetkit/src/utils/env-vars.ts index 424b8bdf38..fe47759440 100644 --- a/rivetkit-typescript/packages/rivetkit/src/utils/env-vars.ts +++ b/rivetkit-typescript/packages/rivetkit/src/utils/env-vars.ts @@ -46,14 +46,10 @@ export const getRivetkitRuntime = (): string | undefined => getEnvUniversal("RIVETKIT_RUNTIME"); export type RuntimeMode = "envoy" | "serverless"; -export const getRivetkitRuntimeMode = (): RuntimeMode => { - const explicit = getEnvUniversal("RIVETKIT_RUNTIME_MODE"); - if (explicit === "envoy" || explicit === "serverless") return explicit; - const railwayId = getEnvUniversal("RAILWAY_DEPLOYMENT_ID"); - if (railwayId !== undefined && railwayId !== "") return "envoy"; - if (getNodeEnv() === "production") return "serverless"; - return "envoy"; -}; +export const getRivetkitRuntimeMode = (): RuntimeMode => + getEnvUniversal("RIVETKIT_RUNTIME_MODE") === "serverless" + ? "serverless" + : "envoy"; export const getRivetkitPublicDir = (): string | undefined => { const value = getEnvUniversal("RIVETKIT_PUBLIC_DIR"); diff --git a/rivetkit-typescript/packages/rivetkit/tests/listener.test.ts b/rivetkit-typescript/packages/rivetkit/tests/listener.test.ts index aeb40155bb..2f3d8d9b60 100644 --- a/rivetkit-typescript/packages/rivetkit/tests/listener.test.ts +++ b/rivetkit-typescript/packages/rivetkit/tests/listener.test.ts @@ -5,73 +5,40 @@ import type { Registry } from "@/registry"; import { getRivetkitRuntimeMode, parsePortEnv } from "@/utils/env-vars"; describe("getRivetkitRuntimeMode", () => { - const KEYS = [ - "RIVETKIT_RUNTIME_MODE", - "RAILWAY_DEPLOYMENT_ID", - "NODE_ENV", - ] as const; - let snapshot: Record; + let snapshot: string | undefined; beforeEach(() => { - snapshot = Object.fromEntries(KEYS.map((k) => [k, process.env[k]])); - for (const k of KEYS) delete process.env[k]; + snapshot = process.env.RIVETKIT_RUNTIME_MODE; + delete process.env.RIVETKIT_RUNTIME_MODE; }); afterEach(() => { - for (const k of KEYS) { - if (snapshot[k] === undefined) delete process.env[k]; - else process.env[k] = snapshot[k]; - } + if (snapshot === undefined) delete process.env.RIVETKIT_RUNTIME_MODE; + else process.env.RIVETKIT_RUNTIME_MODE = snapshot; }); - test("dev default (no env) is envoy", () => { + test("default (unset) is envoy", () => { expect(getRivetkitRuntimeMode()).toBe("envoy"); }); - test("NODE_ENV=production defaults to serverless", () => { - process.env.NODE_ENV = "production"; + test("explicit serverless", () => { + process.env.RIVETKIT_RUNTIME_MODE = "serverless"; expect(getRivetkitRuntimeMode()).toBe("serverless"); }); - test("RAILWAY_DEPLOYMENT_ID set defaults to envoy", () => { - process.env.RAILWAY_DEPLOYMENT_ID = "dep_123"; - expect(getRivetkitRuntimeMode()).toBe("envoy"); - }); - - test("Railway overrides NODE_ENV=production", () => { - process.env.RAILWAY_DEPLOYMENT_ID = "dep_123"; - process.env.NODE_ENV = "production"; - expect(getRivetkitRuntimeMode()).toBe("envoy"); - }); - - test("explicit envoy wins over NODE_ENV=production", () => { + test("explicit envoy", () => { process.env.RIVETKIT_RUNTIME_MODE = "envoy"; - process.env.NODE_ENV = "production"; expect(getRivetkitRuntimeMode()).toBe("envoy"); }); - test("explicit serverless wins over Railway", () => { - process.env.RIVETKIT_RUNTIME_MODE = "serverless"; - process.env.RAILWAY_DEPLOYMENT_ID = "dep_123"; - expect(getRivetkitRuntimeMode()).toBe("serverless"); - }); - - test("empty string falls through to next rule", () => { + test("empty string is envoy", () => { process.env.RIVETKIT_RUNTIME_MODE = ""; - process.env.NODE_ENV = "production"; - expect(getRivetkitRuntimeMode()).toBe("serverless"); + expect(getRivetkitRuntimeMode()).toBe("envoy"); }); - test("unrecognized value falls through to next rule", () => { + test("unrecognized value is envoy", () => { process.env.RIVETKIT_RUNTIME_MODE = "potato"; - process.env.RAILWAY_DEPLOYMENT_ID = "dep_123"; expect(getRivetkitRuntimeMode()).toBe("envoy"); }); - - test("RAILWAY_DEPLOYMENT_ID empty is treated as unset; falls through to NODE_ENV", () => { - process.env.RAILWAY_DEPLOYMENT_ID = ""; - process.env.NODE_ENV = "production"; - expect(getRivetkitRuntimeMode()).toBe("serverless"); - }); }); describe("parsePortEnv", () => { diff --git a/website/src/content/docs/general/environment-variables.mdx b/website/src/content/docs/general/environment-variables.mdx index 03baace7e5..6372582ad9 100644 --- a/website/src/content/docs/general/environment-variables.mdx +++ b/website/src/content/docs/general/environment-variables.mdx @@ -66,8 +66,7 @@ These variables configure how clients connect to your actors. | Environment Variable | Description | |---------------------|-------------| -| `RIVETKIT_RUNTIME_MODE` | Controls how `registry.start()` runs. `envoy` opens a long-lived WebSocket to the engine (Mode A) and auto-upserts a normal runner config to the engine on startup (even against remote endpoints). `serverless` binds an HTTP listener via `registry.listen()` (Mode B) and leaves runner-config management to the caller. Resolution: explicit value > `RAILWAY_DEPLOYMENT_ID` set → `envoy` > `NODE_ENV=production` → `serverless` > dev default `envoy`. | -| `RAILWAY_DEPLOYMENT_ID` | Automatically set by Railway. RivetKit uses presence to default `RIVETKIT_RUNTIME_MODE=envoy` when not explicitly set. | +| `RIVETKIT_RUNTIME_MODE` | Controls how `registry.start()` runs. Defaults to `envoy`: opens a long-lived WebSocket to the engine (Mode A). Set to `serverless` to bind an HTTP listener via `registry.listen()` (Mode B). | | `RIVETKIT_PUBLIC_DIR` | Directory of static assets to serve alongside the framework routes when calling `registry.listen()`. Used as a fallback when `opts.publicDir` is not passed. On auto-listen via `registry.start()`, defaults to `/public` when this env var is unset. | ## Logging