diff --git a/examples/experimental-durable-streams-ai-agent-vercel/src/actors.ts b/examples/experimental-durable-streams-ai-agent-vercel/src/actors.ts index 90e67fcef5..34ac791bc0 100644 --- a/examples/experimental-durable-streams-ai-agent-vercel/src/actors.ts +++ b/examples/experimental-durable-streams-ai-agent-vercel/src/actors.ts @@ -23,7 +23,7 @@ export const aiAgent = actor({ }, onWake: (c) => { - consumeStream(c); + c.keepAwake(consumeStream(c)); }, actions: { @@ -31,12 +31,6 @@ export const aiAgent = actor({ getPromptStreamOffset: (c) => c.state.promptStreamOffset, }, - options: { - // IMPORTANT: Keep actor alive to continuously consume prompts - // - // Future versions will enable sleep/wake for durable streams - noSleep: true, - }, }); async function consumeStream(c: ActorContextOf) { diff --git a/examples/experimental-durable-streams-ai-agent/src/index.ts b/examples/experimental-durable-streams-ai-agent/src/index.ts index dcb4c77179..be10de531a 100644 --- a/examples/experimental-durable-streams-ai-agent/src/index.ts +++ b/examples/experimental-durable-streams-ai-agent/src/index.ts @@ -27,7 +27,7 @@ export const aiAgent = actor({ }, onWake: (c) => { - consumeStream(c); + c.keepAwake(consumeStream(c)); }, actions: { @@ -35,12 +35,6 @@ export const aiAgent = actor({ getPromptStreamOffset: (c) => c.state.promptStreamOffset, }, - options: { - // IMPORTANT: Keep actor alive to continuously consume prompts - // - // Future versions will enable sleep/wake for durable streams - noSleep: true, - }, }); // Register actors and start the server: https://rivet.dev/docs/setup diff --git a/examples/kitchen-sink-vercel/frontend/page-data.ts b/examples/kitchen-sink-vercel/frontend/page-data.ts index eb4b32d356..d26cfc0a30 100644 --- a/examples/kitchen-sink-vercel/frontend/page-data.ts +++ b/examples/kitchen-sink-vercel/frontend/page-data.ts @@ -284,9 +284,6 @@ export const ACTION_TEMPLATES: Record = { { label: "Trigger Sleep", action: "triggerSleep", args: [] }, ], sleepWithLongRpc: [{ label: "Get Counts", action: "getCounts", args: [] }], - sleepWithNoSleepOption: [ - { label: "Get Counts", action: "getCounts", args: [] }, - ], scheduled: [ { label: "Schedule +5s", action: "scheduleTaskAfter", args: [5000] }, { label: "Last Run", action: "getLastRun", args: [] }, @@ -809,7 +806,7 @@ export const PAGE_GROUPS: PageGroup[] = [ href: "https://rivet.dev/docs/actors/lifecycle", }, ], - actors: ["sleep", "sleepWithLongRpc", "sleepWithNoSleepOption"], + actors: ["sleep", "sleepWithLongRpc"], snippet: SNIPPETS.lifecycle, }, { diff --git a/examples/kitchen-sink-vercel/src/actors/lifecycle/sleep.ts b/examples/kitchen-sink-vercel/src/actors/lifecycle/sleep.ts index 7414678e71..a916d8c362 100644 --- a/examples/kitchen-sink-vercel/src/actors/lifecycle/sleep.ts +++ b/examples/kitchen-sink-vercel/src/actors/lifecycle/sleep.ts @@ -175,25 +175,3 @@ export const sleepWithRawWebSocket = actor({ sleepTimeout: SLEEP_TIMEOUT, }, }); - -export const sleepWithNoSleepOption = actor({ - state: { startCount: 0, sleepCount: 0 }, - onWake: (c) => { - c.state.startCount += 1; - }, - onSleep: (c) => { - c.state.sleepCount += 1; - }, - actions: { - getCounts: (c) => { - return { - startCount: c.state.startCount, - sleepCount: c.state.sleepCount, - }; - }, - }, - options: { - sleepTimeout: SLEEP_TIMEOUT, - noSleep: true, - }, -}); diff --git a/examples/kitchen-sink-vercel/src/index.ts b/examples/kitchen-sink-vercel/src/index.ts index ac8661ca8b..4977a8aeb5 100644 --- a/examples/kitchen-sink-vercel/src/index.ts +++ b/examples/kitchen-sink-vercel/src/index.ts @@ -69,7 +69,6 @@ import { import { sleep, sleepWithLongRpc, - sleepWithNoSleepOption, sleepWithRawHttp, sleepWithRawWebSocket, } from "./actors/lifecycle/sleep.ts"; @@ -175,7 +174,6 @@ export const registry = setup({ runWithoutHandler, sleep, sleepWithLongRpc, - sleepWithNoSleepOption, sleepWithRawHttp, sleepWithRawWebSocket, scheduled, diff --git a/examples/kitchen-sink/frontend/page-data.ts b/examples/kitchen-sink/frontend/page-data.ts index aafaedb8e6..f1342dc800 100644 --- a/examples/kitchen-sink/frontend/page-data.ts +++ b/examples/kitchen-sink/frontend/page-data.ts @@ -312,9 +312,6 @@ export const ACTION_TEMPLATES: Record = { { label: "Trigger Sleep", action: "triggerSleep", args: [] }, ], sleepWithLongRpc: [{ label: "Get Counts", action: "getCounts", args: [] }], - sleepWithNoSleepOption: [ - { label: "Get Counts", action: "getCounts", args: [] }, - ], scheduled: [ { label: "Schedule +5s", action: "scheduleTaskAfter", args: [5000] }, { label: "Last Run", action: "getLastRun", args: [] }, @@ -855,7 +852,7 @@ export const PAGE_GROUPS: PageGroup[] = [ href: "https://rivet.dev/docs/actors/lifecycle", }, ], - actors: ["sleep", "sleepWithLongRpc", "sleepWithNoSleepOption"], + actors: ["sleep", "sleepWithLongRpc"], snippet: SNIPPETS.lifecycle, }, { diff --git a/examples/kitchen-sink/src/actors/lifecycle/sleep.ts b/examples/kitchen-sink/src/actors/lifecycle/sleep.ts index 7414678e71..a916d8c362 100644 --- a/examples/kitchen-sink/src/actors/lifecycle/sleep.ts +++ b/examples/kitchen-sink/src/actors/lifecycle/sleep.ts @@ -175,25 +175,3 @@ export const sleepWithRawWebSocket = actor({ sleepTimeout: SLEEP_TIMEOUT, }, }); - -export const sleepWithNoSleepOption = actor({ - state: { startCount: 0, sleepCount: 0 }, - onWake: (c) => { - c.state.startCount += 1; - }, - onSleep: (c) => { - c.state.sleepCount += 1; - }, - actions: { - getCounts: (c) => { - return { - startCount: c.state.startCount, - sleepCount: c.state.sleepCount, - }; - }, - }, - options: { - sleepTimeout: SLEEP_TIMEOUT, - noSleep: true, - }, -}); diff --git a/examples/kitchen-sink/src/index.ts b/examples/kitchen-sink/src/index.ts index 12b7fe4dd9..565f2bc093 100644 --- a/examples/kitchen-sink/src/index.ts +++ b/examples/kitchen-sink/src/index.ts @@ -69,7 +69,6 @@ import { import { sleep, sleepWithLongRpc, - sleepWithNoSleepOption, sleepWithRawHttp, sleepWithRawWebSocket, } from "./actors/lifecycle/sleep.ts"; @@ -181,7 +180,6 @@ export const registry = setup({ runWithoutHandler, sleep, sleepWithLongRpc, - sleepWithNoSleepOption, sleepWithRawHttp, sleepWithRawWebSocket, scheduled, diff --git a/rivetkit-rust/packages/rivetkit-core/CLAUDE.md b/rivetkit-rust/packages/rivetkit-core/CLAUDE.md index 5ac3941a25..fdce9a3e2f 100644 --- a/rivetkit-rust/packages/rivetkit-core/CLAUDE.md +++ b/rivetkit-rust/packages/rivetkit-core/CLAUDE.md @@ -7,7 +7,7 @@ ## Sleep state invariants -- Any mutation that changes a `can_sleep` input must call `ActorContext::reset_sleep_timer()` so the `ActorTask` sleep deadline is re-evaluated. Inputs are: `ready`/`started`, `no_sleep`, `active_http_request_count`, `sleep_keep_awake_count`, `sleep_internal_keep_awake_count`, `pending_disconnect_count`, `conns()`, and `websocket_callback_count`. Missing this call leaves the sleep timer armed against stale state and triggers the `"sleep idle deadline elapsed but actor stayed awake"` warning on the next tick. +- Any mutation that changes a `can_sleep` input must call `ActorContext::reset_sleep_timer()` so the `ActorTask` sleep deadline is re-evaluated. Inputs are: `ready`/`started`, `active_http_request_count`, `sleep_keep_awake_count`, `sleep_internal_keep_awake_count`, `pending_disconnect_count`, `conns()`, and `websocket_callback_count`. Missing this call leaves the sleep timer armed against stale state and triggers the `"sleep idle deadline elapsed but actor stayed awake"` warning on the next tick. - Runtime-owned promises that must drain during shutdown should use `ActorContext::register_task(...)`, not public `wait_until(...)`, so metrics and runtime intent stay distinct. Registered tasks must race user work against `shutdown_deadline_token()` so shutdown cannot hang forever. - `ctx.sleep()` and `ctx.destroy()` return `Result<()>`. They error with `ActorLifecycleError::Starting` when called before startup completes and `ActorLifecycleError::Stopping` if the requested flag has already been set this generation (atomic `swap(true, ...)`). Internal idle-timer paths log and suppress the already-requested error. - The grace deadline path (`on_sleep_grace_deadline`) aborts the user `run` handle and cancels `shutdown_deadline_token()`. Foreign-runtime adapters running `onSleep` / `onDestroy` must observe that token via `tokio::select!` so SQLite teardown does not race user cleanup work. diff --git a/rivetkit-rust/packages/rivetkit-core/src/actor/config.rs b/rivetkit-rust/packages/rivetkit-core/src/actor/config.rs index fac01c866f..dfb7d80973 100644 --- a/rivetkit-rust/packages/rivetkit-core/src/actor/config.rs +++ b/rivetkit-rust/packages/rivetkit-core/src/actor/config.rs @@ -74,7 +74,6 @@ pub struct ActorConfig { pub on_migrate_timeout: Duration, pub action_timeout: Duration, pub sleep_timeout: Duration, - pub no_sleep: bool, pub sleep_grace_period: Duration, pub sleep_grace_period_overridden: bool, pub connection_liveness_timeout: Duration, @@ -109,7 +108,6 @@ pub struct ActorConfigInput { pub on_migrate_timeout_ms: Option, pub action_timeout_ms: Option, pub sleep_timeout_ms: Option, - pub no_sleep: Option, pub sleep_grace_period_ms: Option, pub connection_liveness_timeout_ms: Option, pub connection_liveness_interval_ms: Option, @@ -160,9 +158,6 @@ impl ActorConfig { if let Some(value) = config.sleep_timeout_ms { actor_config.sleep_timeout = duration_ms(value); } - if let Some(value) = config.no_sleep { - actor_config.no_sleep = value; - } if let Some(value) = config.sleep_grace_period_ms { actor_config.sleep_grace_period = duration_ms(value); actor_config.sleep_grace_period_overridden = true; @@ -224,7 +219,6 @@ impl Default for ActorConfig { on_migrate_timeout: DEFAULT_ON_MIGRATE_TIMEOUT, action_timeout: DEFAULT_ACTION_TIMEOUT, sleep_timeout: DEFAULT_SLEEP_TIMEOUT, - no_sleep: false, sleep_grace_period: DEFAULT_SLEEP_GRACE_PERIOD, sleep_grace_period_overridden: false, connection_liveness_timeout: DEFAULT_CONNECTION_LIVENESS_TIMEOUT, diff --git a/rivetkit-rust/packages/rivetkit-core/src/actor/sleep.rs b/rivetkit-rust/packages/rivetkit-core/src/actor/sleep.rs index 199b00bdbb..bbd738859e 100644 --- a/rivetkit-rust/packages/rivetkit-core/src/actor/sleep.rs +++ b/rivetkit-rust/packages/rivetkit-core/src/actor/sleep.rs @@ -58,7 +58,6 @@ pub(crate) struct SleepState { pub(crate) enum CanSleep { Yes, NotReady, - NoSleep, ActiveHttpRequests, ActiveKeepAwake, ActiveInternalKeepAwake, @@ -223,13 +222,9 @@ impl ActorContext { } pub(crate) async fn can_arm_sleep_timer(&self) -> CanSleep { - let config = self.sleep_state_config(); if !self.0.sleep.lifecycle_started.load(Ordering::SeqCst) { return CanSleep::NotReady; } - if config.no_sleep { - return CanSleep::NoSleep; - } if self.active_http_request_count() > 0 { return CanSleep::ActiveHttpRequests; } diff --git a/rivetkit-rust/packages/rivetkit-core/tests/config.rs b/rivetkit-rust/packages/rivetkit-core/tests/config.rs index c4e88504e3..038a053533 100644 --- a/rivetkit-rust/packages/rivetkit-core/tests/config.rs +++ b/rivetkit-rust/packages/rivetkit-core/tests/config.rs @@ -45,7 +45,6 @@ mod moved_tests { assert_eq!(config.on_migrate_timeout, default.on_migrate_timeout); assert_eq!(config.action_timeout, default.action_timeout); assert_eq!(config.sleep_timeout, default.sleep_timeout); - assert_eq!(config.no_sleep, default.no_sleep); assert_eq!(config.sleep_grace_period, default.sleep_grace_period); assert_eq!( config.sleep_grace_period_overridden, diff --git a/rivetkit-rust/packages/rivetkit-core/tests/context.rs b/rivetkit-rust/packages/rivetkit-core/tests/context.rs index bb1bb2443d..2a335f3088 100644 --- a/rivetkit-rust/packages/rivetkit-core/tests/context.rs +++ b/rivetkit-rust/packages/rivetkit-core/tests/context.rs @@ -26,7 +26,6 @@ fn build_applies_actor_config_to_owned_subsystems() { config.create_conn_state_timeout = std::time::Duration::from_millis(123); config.connection_liveness_timeout = std::time::Duration::from_millis(456); config.sleep_timeout = std::time::Duration::from_millis(789); - config.no_sleep = true; let ctx = ActorContext::build( "configured-actor".to_owned(), @@ -57,7 +56,6 @@ fn build_applies_actor_config_to_owned_subsystems() { let sleep_config = ctx.sleep_config(); assert_eq!(sleep_config.sleep_timeout, config.sleep_timeout); - assert_eq!(sleep_config.no_sleep, config.no_sleep); } #[tokio::test] diff --git a/rivetkit-typescript/artifacts/actor-config.json b/rivetkit-typescript/artifacts/actor-config.json index dbf31c0b10..1fec33c03b 100644 --- a/rivetkit-typescript/artifacts/actor-config.json +++ b/rivetkit-typescript/artifacts/actor-config.json @@ -12,7 +12,7 @@ "description": "Initial connection state value. Cannot be used with createConnState." }, "createConnState": { - "description": "Function to create connection state. Receives context and connection params. Cannot be used with connState." + "description": "Function to create connection state. Receives context and connection params. The pending connection is not visible in c.conns until this succeeds. Cannot be used with connState." }, "vars": { "description": "Initial ephemeral variables value. Cannot be used with createVars." @@ -45,10 +45,10 @@ "description": "Called when the actor's state changes. State changes within this hook won't trigger recursion." }, "onBeforeConnect": { - "description": "Called before a client connects. Throw an error to reject the connection." + "description": "Called before a client connects. Throw an error to reject the connection. The pending connection is not visible in c.conns while this runs." }, "onConnect": { - "description": "Called when a client successfully connects." + "description": "Called when a client successfully connects. The connection is visible in c.conns before this runs." }, "onDisconnect": { "description": "Called when a client disconnects." @@ -130,11 +130,7 @@ "type": "number" }, "sleepGracePeriod": { - "description": "Max time in ms for the graceful sleep window. Covers lifecycle hooks, waitUntil, async raw WebSocket handlers, and disconnect callbacks. Default: 15000.", - "type": "number" - }, - "onDestroyTimeout": { - "description": "Graceful destroy shutdown window in ms. Default: 15000", + "description": "Max time in ms for the graceful shutdown window. Covers lifecycle hooks (onSleep, onDestroy), the run handler wait, async raw WebSocket handlers, disconnect callbacks, and final state serialization. Default: 15000.", "type": "number" }, "stateSaveInterval": { @@ -145,10 +141,6 @@ "description": "Timeout in ms for action handlers. Default: 60000", "type": "number" }, - "waitUntilTimeout": { - "description": "Deprecated. Legacy timeout in ms for waitUntil when sleepGracePeriod is not set. Default: 15000", - "type": "number" - }, "connectionLivenessTimeout": { "description": "Timeout in ms for connection liveness checks. Default: 2500", "type": "number" @@ -157,10 +149,6 @@ "description": "Interval in ms between connection liveness checks. Default: 5000", "type": "number" }, - "noSleep": { - "description": "Deprecated. If true, the actor will never sleep. Use c.keepAwake(promise) to scope keep-awake to a specific operation instead. Default: false", - "type": "boolean" - }, "sleepTimeout": { "description": "Time in ms of inactivity before the actor sleeps. Default: 30000", "type": "number" @@ -191,4 +179,4 @@ }, "additionalProperties": false, "title": "RivetKit Actor Configuration" -} +} \ No newline at end of file diff --git a/rivetkit-typescript/packages/rivetkit-napi/index.d.ts b/rivetkit-typescript/packages/rivetkit-napi/index.d.ts index 3bb899f1da..962eeb464f 100644 --- a/rivetkit-typescript/packages/rivetkit-napi/index.d.ts +++ b/rivetkit-typescript/packages/rivetkit-napi/index.d.ts @@ -67,7 +67,6 @@ export interface JsActorConfig { actionTimeoutMs?: number onRequestTimeoutMs?: number sleepTimeoutMs?: number - noSleep?: boolean sleepGracePeriodMs?: number connectionLivenessTimeoutMs?: number connectionLivenessIntervalMs?: number diff --git a/rivetkit-typescript/packages/rivetkit-napi/src/actor_factory.rs b/rivetkit-typescript/packages/rivetkit-napi/src/actor_factory.rs index df67d6044b..315b1f0d10 100644 --- a/rivetkit-typescript/packages/rivetkit-napi/src/actor_factory.rs +++ b/rivetkit-typescript/packages/rivetkit-napi/src/actor_factory.rs @@ -82,7 +82,6 @@ pub struct JsActorConfig { pub action_timeout_ms: Option, pub on_request_timeout_ms: Option, pub sleep_timeout_ms: Option, - pub no_sleep: Option, pub sleep_grace_period_ms: Option, pub connection_liveness_timeout_ms: Option, pub connection_liveness_interval_ms: Option, @@ -1062,7 +1061,6 @@ impl From for ActorConfigInput { on_migrate_timeout_ms: value.on_migrate_timeout_ms, action_timeout_ms: value.action_timeout_ms, sleep_timeout_ms: value.sleep_timeout_ms, - no_sleep: value.no_sleep, sleep_grace_period_ms: value.sleep_grace_period_ms, connection_liveness_timeout_ms: value.connection_liveness_timeout_ms, connection_liveness_interval_ms: value.connection_liveness_interval_ms, diff --git a/rivetkit-typescript/packages/rivetkit-wasm/src/lib.rs b/rivetkit-typescript/packages/rivetkit-wasm/src/lib.rs index 6411f75c47..b3cf99d27b 100644 --- a/rivetkit-typescript/packages/rivetkit-wasm/src/lib.rs +++ b/rivetkit-typescript/packages/rivetkit-wasm/src/lib.rs @@ -118,7 +118,12 @@ pub struct WasmServeConfig { pub token: Option, pub namespace: String, pub pool_name: String, + pub envoy_key: Option, pub engine_binary_path: Option, + pub dev_serverless_url: Option, + pub dev_serverless_manual: bool, + pub dev_serverless_drain_timeout: Option, + pub dev_serverless_request_timeout: Option, pub handle_inspector_http_in_runtime: Option, pub inspector_test_token: Option, pub serverless_base_path: Option, @@ -149,7 +154,12 @@ impl From for ServeConfig { token: config.token, namespace: config.namespace, pool_name: config.pool_name, + envoy_key: config.envoy_key, engine_binary_path: config.engine_binary_path.map(PathBuf::from), + dev_serverless_url: config.dev_serverless_url, + dev_serverless_manual: config.dev_serverless_manual, + dev_serverless_drain_timeout: config.dev_serverless_drain_timeout, + dev_serverless_request_timeout: config.dev_serverless_request_timeout, handle_inspector_http_in_runtime: config .handle_inspector_http_in_runtime .unwrap_or(false), @@ -193,7 +203,6 @@ pub struct WasmActorConfig { pub action_timeout_ms: Option, pub on_request_timeout_ms: Option, pub sleep_timeout_ms: Option, - pub no_sleep: Option, pub sleep_grace_period_ms: Option, pub connection_liveness_timeout_ms: Option, pub connection_liveness_interval_ms: Option, @@ -223,7 +232,6 @@ impl From for ActorConfigInput { on_migrate_timeout_ms: config.on_migrate_timeout_ms, action_timeout_ms: config.action_timeout_ms, sleep_timeout_ms: config.sleep_timeout_ms, - no_sleep: config.no_sleep, sleep_grace_period_ms: config.sleep_grace_period_ms, connection_liveness_timeout_ms: config.connection_liveness_timeout_ms, connection_liveness_interval_ms: config.connection_liveness_interval_ms, @@ -2840,7 +2848,12 @@ mod tests { token: None, namespace: "default".to_owned(), pool_name: "default".to_owned(), + envoy_key: None, engine_binary_path, + dev_serverless_url: None, + dev_serverless_manual: false, + dev_serverless_drain_timeout: None, + dev_serverless_request_timeout: None, handle_inspector_http_in_runtime: None, inspector_test_token: None, serverless_base_path: None, diff --git a/rivetkit-typescript/packages/rivetkit/fixtures/driver-test-suite/actors/sleepWithNoSleepOption.ts b/rivetkit-typescript/packages/rivetkit/fixtures/driver-test-suite/actors/sleepWithNoSleepOption.ts deleted file mode 100644 index 716d18e992..0000000000 --- a/rivetkit-typescript/packages/rivetkit/fixtures/driver-test-suite/actors/sleepWithNoSleepOption.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { sleepWithNoSleepOption } from "../sleep"; - -export default sleepWithNoSleepOption; diff --git a/rivetkit-typescript/packages/rivetkit/fixtures/driver-test-suite/registry-static.ts b/rivetkit-typescript/packages/rivetkit/fixtures/driver-test-suite/registry-static.ts index 832e1065ee..c220b4fb04 100644 --- a/rivetkit-typescript/packages/rivetkit/fixtures/driver-test-suite/registry-static.ts +++ b/rivetkit-typescript/packages/rivetkit/fixtures/driver-test-suite/registry-static.ts @@ -102,7 +102,6 @@ import { sleepRawWsAddEventListenerClose, sleepRawWsAddEventListenerMessage, sleepWithLongRpc, - sleepWithNoSleepOption, sleepWithRawHttp, sleepWithRawWebSocket, sleepWithWaitUntilMessage, @@ -200,7 +199,6 @@ export const registry = setup({ sleepWithLongRpc, sleepWithRawHttp, sleepWithRawWebSocket, - sleepWithNoSleepOption, sleepWithWaitUntilMessage, sleepRawWsAddEventListenerMessage, sleepRawWsAddEventListenerClose, diff --git a/rivetkit-typescript/packages/rivetkit/fixtures/driver-test-suite/sleep.ts b/rivetkit-typescript/packages/rivetkit/fixtures/driver-test-suite/sleep.ts index 56fb3aa865..f339d12e51 100644 --- a/rivetkit-typescript/packages/rivetkit/fixtures/driver-test-suite/sleep.ts +++ b/rivetkit-typescript/packages/rivetkit/fixtures/driver-test-suite/sleep.ts @@ -596,25 +596,3 @@ export const sleepAbortListenerVarsActor = actor({ sleepTimeout: SLEEP_TIMEOUT, }, }); - -export const sleepWithNoSleepOption = actor({ - state: { startCount: 0, sleepCount: 0 }, - onWake: (c) => { - c.state.startCount += 1; - }, - onSleep: (c) => { - c.state.sleepCount += 1; - }, - actions: { - getCounts: (c) => { - return { - startCount: c.state.startCount, - sleepCount: c.state.sleepCount, - }; - }, - }, - options: { - sleepTimeout: SLEEP_TIMEOUT, - noSleep: true, - }, -}); diff --git a/rivetkit-typescript/packages/rivetkit/fixtures/driver-test-suite/start-stop-race.ts b/rivetkit-typescript/packages/rivetkit/fixtures/driver-test-suite/start-stop-race.ts index 3829970adb..47f2c3e227 100644 --- a/rivetkit-typescript/packages/rivetkit/fixtures/driver-test-suite/start-stop-race.ts +++ b/rivetkit-typescript/packages/rivetkit/fixtures/driver-test-suite/start-stop-race.ts @@ -83,6 +83,6 @@ export const lifecycleObserver = actor({ }, }, options: { - noSleep: true, + sleepTimeout: 60_000, }, }); diff --git a/rivetkit-typescript/packages/rivetkit/src/actor/config.ts b/rivetkit-typescript/packages/rivetkit/src/actor/config.ts index b6bca6b514..ebe823df8b 100644 --- a/rivetkit-typescript/packages/rivetkit/src/actor/config.ts +++ b/rivetkit-typescript/packages/rivetkit/src/actor/config.ts @@ -872,16 +872,10 @@ const InstanceActorOptionsBaseSchema = z .number() .positive() .default(DEFAULT_SLEEP_GRACE_PERIOD), - /** @deprecated `onDestroyTimeout` is folded into `sleepGracePeriod`, which now bounds the entire graceful shutdown window for both sleep and destroy. Will be removed in 2.2.0. */ - onDestroyTimeout: z.number().positive().optional(), - /** @deprecated `waitUntilTimeout` is folded into `sleepGracePeriod`, which now bounds the entire graceful shutdown window for both sleep and destroy. Will be removed in 2.2.0. */ - waitUntilTimeout: z.number().positive().optional(), stateSaveInterval: z.number().positive().default(1_000), actionTimeout: z.number().positive().default(60_000), connectionLivenessTimeout: z.number().positive().default(2500), connectionLivenessInterval: z.number().positive().default(5000), - /** @deprecated Use `c.keepAwake(promise)` to scope keep-awake to a specific operation. Will be removed in 2.2.0. */ - noSleep: z.boolean().default(false), sleepTimeout: z.number().positive().default(30_000), maxQueueSize: z.number().positive().default(1000), maxQueueMessageSize: z @@ -1771,18 +1765,6 @@ export const DocActorOptionsSchema = z .describe( `Max time in ms for the graceful shutdown window. Covers lifecycle hooks (onSleep, onDestroy), the run handler wait, async raw WebSocket handlers, disconnect callbacks, and final state serialization. Default: ${DEFAULT_SLEEP_GRACE_PERIOD}.`, ), - onDestroyTimeout: z - .number() - .optional() - .describe( - "Deprecated. Folded into sleepGracePeriod, which now bounds the entire graceful shutdown window for both sleep and destroy. Will be removed in 2.2.0.", - ), - waitUntilTimeout: z - .number() - .optional() - .describe( - "Deprecated. Folded into sleepGracePeriod, which now bounds the entire graceful shutdown window for both sleep and destroy. Will be removed in 2.2.0.", - ), stateSaveInterval: z .number() .optional() @@ -1805,12 +1787,6 @@ export const DocActorOptionsSchema = z .describe( "Interval in ms between connection liveness checks. Default: 5000", ), - noSleep: z - .boolean() - .optional() - .describe( - "Deprecated. If true, the actor will never sleep. Use c.keepAwake(promise) to scope keep-awake to a specific operation instead. Default: false", - ), sleepTimeout: z .number() .optional() diff --git a/rivetkit-typescript/packages/rivetkit/src/actor/definition.ts b/rivetkit-typescript/packages/rivetkit/src/actor/definition.ts index 5e6e7a2c66..5bae61f306 100644 --- a/rivetkit-typescript/packages/rivetkit/src/actor/definition.ts +++ b/rivetkit-typescript/packages/rivetkit/src/actor/definition.ts @@ -1,24 +1,8 @@ import type { RegistryConfig } from "@/registry/config"; import { ActorConfigSchema, type Actions, type ActorConfig, type ActorConfigInput } from "./config"; -import { loggerWithoutContext } from "./log"; import type { AnyDatabaseProvider } from "@/common/database/config"; import type { EventSchemaConfig, QueueSchemaConfig } from "./schema"; -const warnedDeprecatedTimeoutKeys = new Set(); - -function warnDeprecatedShutdownTimeoutKeys(options: unknown) { - if (!options || typeof options !== "object") return; - const opts = options as Record; - for (const key of ["onDestroyTimeout", "waitUntilTimeout"]) { - if (opts[key] !== undefined && !warnedDeprecatedTimeoutKeys.has(key)) { - warnedDeprecatedTimeoutKeys.add(key); - loggerWithoutContext().warn({ - msg: `actor option \`${key}\` is deprecated and is now ignored. Configure \`sleepGracePeriod\` instead, which bounds the entire graceful shutdown window for both sleep and destroy. Will be removed in 2.2.0.`, - }); - } - } -} - export interface BaseActorDefinition< S, CP, @@ -184,9 +168,6 @@ export function actor< TQueues, TActions > { - warnDeprecatedShutdownTimeoutKeys( - (input as { options?: unknown } | undefined)?.options, - ); const config = ActorConfigSchema.parse(input) as ActorConfig< TState, TConnParams, diff --git a/rivetkit-typescript/packages/rivetkit/src/actor/instance/mod.ts b/rivetkit-typescript/packages/rivetkit/src/actor/instance/mod.ts index 14ee5bbf28..403c8e603d 100644 --- a/rivetkit-typescript/packages/rivetkit/src/actor/instance/mod.ts +++ b/rivetkit-typescript/packages/rivetkit/src/actor/instance/mod.ts @@ -2336,7 +2336,7 @@ export class ActorInstance< } resetSleepTimer() { - if (this.#config.options.noSleep || !this.#sleepingSupported) return; + if (!this.#sleepingSupported) return; if (this.#stopCalled) return; const canSleep = this.#canSleep(); diff --git a/rivetkit-typescript/packages/rivetkit/src/registry/native.ts b/rivetkit-typescript/packages/rivetkit/src/registry/native.ts index 62cbfb34c8..9337441d1b 100644 --- a/rivetkit-typescript/packages/rivetkit/src/registry/native.ts +++ b/rivetkit-typescript/packages/rivetkit/src/registry/native.ts @@ -3336,7 +3336,6 @@ function buildActorConfig( onMigrateTimeoutMs: options.onMigrateTimeout as number | undefined, actionTimeoutMs: options.actionTimeout as number | undefined, sleepTimeoutMs: options.sleepTimeout as number | undefined, - noSleep: options.noSleep as boolean | undefined, sleepGracePeriodMs: options.sleepGracePeriod as number | undefined, connectionLivenessTimeoutMs: options.connectionLivenessTimeout as | number diff --git a/rivetkit-typescript/packages/rivetkit/src/registry/runtime.ts b/rivetkit-typescript/packages/rivetkit/src/registry/runtime.ts index b109aa5847..60a4745582 100644 --- a/rivetkit-typescript/packages/rivetkit/src/registry/runtime.ts +++ b/rivetkit-typescript/packages/rivetkit/src/registry/runtime.ts @@ -214,7 +214,6 @@ export interface RuntimeActorConfig { actionTimeoutMs?: number; onRequestTimeoutMs?: number; sleepTimeoutMs?: number; - noSleep?: boolean; sleepGracePeriodMs?: number; connectionLivenessTimeoutMs?: number; connectionLivenessIntervalMs?: number; diff --git a/rivetkit-typescript/packages/rivetkit/tests/driver/actor-sleep.test.ts b/rivetkit-typescript/packages/rivetkit/tests/driver/actor-sleep.test.ts index 28fc0a76d6..0ba75b4d12 100644 --- a/rivetkit-typescript/packages/rivetkit/tests/driver/actor-sleep.test.ts +++ b/rivetkit-typescript/packages/rivetkit/tests/driver/actor-sleep.test.ts @@ -689,40 +689,6 @@ describeDriverMatrix("Actor Sleep", (driverTestConfig) => { } }); - test("noSleep option disables sleeping", async (c) => { - const { client } = await setupDriverTest(c, driverTestConfig); - - // Create actor with noSleep option - const sleepActor = client.sleepWithNoSleepOption.getOrCreate(); - - // Verify initial state - { - const { startCount, sleepCount } = await sleepActor.getCounts(); - expect(sleepCount).toBe(0); - expect(startCount).toBe(1); - } - - // Wait longer than sleep timeout - await waitFor(driverTestConfig, SLEEP_TIMEOUT + 250); - - // Actor should NOT have slept due to noSleep option - { - const { startCount, sleepCount } = await sleepActor.getCounts(); - expect(sleepCount).toBe(0); // Never slept - expect(startCount).toBe(1); // Still the same instance - } - - // Wait even longer to be sure - await waitFor(driverTestConfig, SLEEP_TIMEOUT + 250); - - // Actor should still not have slept - { - const { startCount, sleepCount } = await sleepActor.getCounts(); - expect(sleepCount).toBe(0); // Never slept - expect(startCount).toBe(1); // Still the same instance - } - }); - test("async websocket addEventListener message handler delays sleep", async (c) => { const { client } = await setupDriverTest(c, driverTestConfig); diff --git a/rivetkit-typescript/packages/rivetkit/tests/registry-constructor.test.ts b/rivetkit-typescript/packages/rivetkit/tests/registry-constructor.test.ts index a41845e7b6..cb73619c4c 100644 --- a/rivetkit-typescript/packages/rivetkit/tests/registry-constructor.test.ts +++ b/rivetkit-typescript/packages/rivetkit/tests/registry-constructor.test.ts @@ -83,4 +83,19 @@ describe("Registry constructor", () => { /registry\.listen\(\) cannot be used after registry\.fetchHandler\(\)/, ); }); + + test.each(["noSleep", "onDestroyTimeout", "waitUntilTimeout"])( + "rejects removed actor option %s", + (option) => { + expect(() => + actor({ + state: {}, + actions: {}, + options: { + [option]: option === "noSleep" ? true : 1_000, + }, + } as never), + ).toThrow(/unrecognized key/i); + }, + ); });