From 0df30edd50c2be2bc80ae532b9c4533c810d01ca Mon Sep 17 00:00:00 2001 From: Nathan Flurry Date: Thu, 23 Apr 2026 20:12:57 -0700 Subject: [PATCH] chore(rivetkit): remove legacy metrics --- .../rivetkit-core/src/actor/config.rs | 11 ++ .../packages/rivetkit-core/src/actor/mod.rs | 2 +- .../packages/rivetkit-core/src/lib.rs | 2 +- .../rivetkit-core/src/registry/inspector.rs | 9 +- .../packages/rivetkit-napi/index.d.ts | 4 + .../rivetkit-napi/src/actor_factory.rs | 15 +- .../packages/rivetkit/src/registry/native.ts | 130 +++--------------- 7 files changed, 60 insertions(+), 113 deletions(-) diff --git a/rivetkit-rust/packages/rivetkit-core/src/actor/config.rs b/rivetkit-rust/packages/rivetkit-core/src/actor/config.rs index cca07721fd..5d23695d83 100644 --- a/rivetkit-rust/packages/rivetkit-core/src/actor/config.rs +++ b/rivetkit-rust/packages/rivetkit-core/src/actor/config.rs @@ -53,6 +53,11 @@ pub struct ActorConfigOverrides { pub wait_until_timeout: Option, } +#[derive(Clone, Debug)] +pub struct ActionDefinition { + pub name: String, +} + #[derive(Clone, Debug)] pub struct ActorConfig { pub name: Option, @@ -83,6 +88,7 @@ pub struct ActorConfig { pub preload_max_workflow_bytes: Option, pub preload_max_connections_bytes: Option, pub overrides: Option, + pub actions: Vec, } /// Sparse, serialization-friendly actor configuration. All fields are optional with millisecond integers instead of Duration. Used at runtime boundaries (NAPI, config files). Convert to ActorConfig via ActorConfig::from_input(). @@ -110,6 +116,7 @@ pub struct ActorConfigInput { pub max_outgoing_message_size: Option, pub preload_max_workflow_bytes: Option, pub preload_max_connections_bytes: Option, + pub actions: Option>, } impl ActorConfig { @@ -180,6 +187,9 @@ impl ActorConfig { actor_config.preload_max_connections_bytes = config .preload_max_connections_bytes .map(|value| value as u64); + if let Some(actions) = config.actions { + actor_config.actions = actions; + } actor_config } @@ -243,6 +253,7 @@ impl Default for ActorConfig { preload_max_workflow_bytes: None, preload_max_connections_bytes: None, overrides: None, + actions: Vec::new(), } } } diff --git a/rivetkit-rust/packages/rivetkit-core/src/actor/mod.rs b/rivetkit-rust/packages/rivetkit-core/src/actor/mod.rs index c79f22c5de..888fabd08b 100644 --- a/rivetkit-rust/packages/rivetkit-core/src/actor/mod.rs +++ b/rivetkit-rust/packages/rivetkit-core/src/actor/mod.rs @@ -20,7 +20,7 @@ pub mod task_types; pub(crate) mod work_registry; pub use action::ActionDispatchError; -pub use config::{ActorConfig, ActorConfigOverrides, CanHibernateWebSocket}; +pub use config::{ActionDefinition, ActorConfig, ActorConfigOverrides, CanHibernateWebSocket}; pub use connection::ConnHandle; pub use context::{ActorContext, WebSocketCallbackRegion}; pub use factory::{ActorEntryFn, ActorFactory}; diff --git a/rivetkit-rust/packages/rivetkit-core/src/lib.rs b/rivetkit-rust/packages/rivetkit-core/src/lib.rs index 8e63c69643..d419086246 100644 --- a/rivetkit-rust/packages/rivetkit-core/src/lib.rs +++ b/rivetkit-rust/packages/rivetkit-core/src/lib.rs @@ -10,7 +10,7 @@ pub use actor::{kv, sqlite}; pub use actor::action::ActionDispatchError; pub use actor::config::{ - ActorConfig, ActorConfigInput, ActorConfigOverrides, CanHibernateWebSocket, + ActionDefinition, ActorConfig, ActorConfigInput, ActorConfigOverrides, CanHibernateWebSocket, }; pub use actor::connection::ConnHandle; pub use actor::context::{ActorContext, WebSocketCallbackRegion}; diff --git a/rivetkit-rust/packages/rivetkit-core/src/registry/inspector.rs b/rivetkit-rust/packages/rivetkit-core/src/registry/inspector.rs index 9c2b5966bf..4ab97fab9c 100644 --- a/rivetkit-rust/packages/rivetkit-core/src/registry/inspector.rs +++ b/rivetkit-rust/packages/rivetkit-core/src/registry/inspector.rs @@ -573,8 +573,13 @@ pub(super) fn build_actor_inspector() -> Inspector { } pub(super) fn inspector_rpcs(instance: &ActorTaskHandle) -> Vec { - let _ = instance; - Vec::new() + instance + .factory + .config() + .actions + .iter() + .map(|action| action.name.clone()) + .collect() } pub(super) fn inspector_request_url(request: &Request) -> Result { diff --git a/rivetkit-typescript/packages/rivetkit-napi/index.d.ts b/rivetkit-typescript/packages/rivetkit-napi/index.d.ts index 4d66b59a2b..5dff314187 100644 --- a/rivetkit-typescript/packages/rivetkit-napi/index.d.ts +++ b/rivetkit-typescript/packages/rivetkit-napi/index.d.ts @@ -44,6 +44,9 @@ export interface JsQueueSendResult { status: string response?: Buffer } +export interface JsActionDefinition { + name: string +} export interface JsActorConfig { name?: string icon?: string @@ -72,6 +75,7 @@ export interface JsActorConfig { maxOutgoingMessageSize?: number preloadMaxWorkflowBytes?: number preloadMaxConnectionsBytes?: number + actions?: Array } export interface JsBindParam { kind: string diff --git a/rivetkit-typescript/packages/rivetkit-napi/src/actor_factory.rs b/rivetkit-typescript/packages/rivetkit-napi/src/actor_factory.rs index d0b2af8404..0a77ff5249 100644 --- a/rivetkit-typescript/packages/rivetkit-napi/src/actor_factory.rs +++ b/rivetkit-typescript/packages/rivetkit-napi/src/actor_factory.rs @@ -10,7 +10,7 @@ use napi::{Env, JsFunction, JsObject}; use napi_derive::napi; use rivet_error::{MacroMarker, RivetError, RivetErrorSchema}; use rivetkit_core::{ - ActorConfig, ActorConfigInput, ActorContext as CoreActorContext, + ActionDefinition, ActorConfig, ActorConfigInput, ActorContext as CoreActorContext, ActorFactory as CoreActorFactory, ConnHandle as CoreConnHandle, Request, Response, WebSocket as CoreWebSocket, }; @@ -54,6 +54,12 @@ pub struct JsQueueSendResult { pub response: Option, } +#[napi(object)] +#[derive(Clone, Default)] +pub struct JsActionDefinition { + pub name: String, +} + #[napi(object)] #[derive(Clone, Default)] pub struct JsActorConfig { @@ -84,6 +90,7 @@ pub struct JsActorConfig { pub max_outgoing_message_size: Option, pub preload_max_workflow_bytes: Option, pub preload_max_connections_bytes: Option, + pub actions: Option>, } #[derive(Clone)] @@ -1048,6 +1055,12 @@ impl From for ActorConfigInput { max_outgoing_message_size: value.max_outgoing_message_size, preload_max_workflow_bytes: value.preload_max_workflow_bytes, preload_max_connections_bytes: value.preload_max_connections_bytes, + actions: value.actions.map(|actions| { + actions + .into_iter() + .map(|action| ActionDefinition { name: action.name }) + .collect() + }), } } } diff --git a/rivetkit-typescript/packages/rivetkit/src/registry/native.ts b/rivetkit-typescript/packages/rivetkit/src/registry/native.ts index 2e318243a0..06152a19e2 100644 --- a/rivetkit-typescript/packages/rivetkit/src/registry/native.ts +++ b/rivetkit-typescript/packages/rivetkit/src/registry/native.ts @@ -3083,6 +3083,11 @@ function buildActorConfig( preloadMaxConnectionsBytes: options.preloadMaxConnectionsBytes as | number | undefined, + actions: Object.keys( + (config.actions ?? {}) as Record, + ) + .sort() + .map((name) => ({ name })), }; } @@ -3230,106 +3235,6 @@ export function buildNativeFactory( ); const workflowState = async () => (await getNativeWorkflowInspector(ctx)?.getState?.()) ?? null; - const metricsResponse = (actorCtx: NativeActorContextAdapter) => { - const sqliteMetrics = - databaseProvider !== undefined - ? (actorCtx.sql.getSqliteVfsMetrics?.() ?? null) - : null; - const commitCount = - databaseProvider === undefined - ? 0 - : Math.max(sqliteMetrics?.commitCount ?? 0, 1); - const nsToMs = (ns: number) => ns / 1_000_000; - const phaseMs = (ns: number) => - commitCount > 0 ? Math.max(nsToMs(ns), 0.001) : 0; - return { - kv_operations: { - type: "labeled_timing", - help: "KV round trips by operation type", - values: { - get: { calls: 0, totalMs: 0, keys: 0 }, - getBatch: { calls: 0, totalMs: 0, keys: 0 }, - put: { calls: 0, totalMs: 0, keys: 0 }, - putBatch: { calls: 0, totalMs: 0, keys: 0 }, - deleteBatch: { calls: 0, totalMs: 0, keys: 0 }, - }, - }, - sqlite_commit_phases: { - type: "labeled_timing", - help: "SQLite VFS commit phase totals captured by the native VFS", - values: { - request_build: { - calls: commitCount, - totalMs: phaseMs( - sqliteMetrics?.requestBuildNs ?? 0, - ), - keys: 0, - }, - serialize: { - calls: commitCount, - totalMs: phaseMs(sqliteMetrics?.serializeNs ?? 0), - keys: 0, - }, - transport: { - calls: commitCount, - totalMs: phaseMs(sqliteMetrics?.transportNs ?? 0), - keys: 0, - }, - state_update: { - calls: commitCount, - totalMs: phaseMs(sqliteMetrics?.stateUpdateNs ?? 0), - keys: 0, - }, - }, - }, - startup_total_ms: { - type: "gauge", - help: "Total actor startup time in milliseconds", - value: 1, - }, - startup_kv_round_trips: { - type: "gauge", - help: "KV round-trips during startup", - value: 0, - }, - startup_is_new: { - type: "gauge", - help: "1 if new actor, 0 if existing", - value: 0, - }, - startup_internal_load_state_ms: { - type: "gauge", - help: "Time to load persisted state", - value: 0, - }, - startup_internal_init_queue_ms: { - type: "gauge", - help: "Time to initialize queue state", - value: 0, - }, - startup_internal_init_inspector_token_ms: { - type: "gauge", - help: "Time to initialize inspector token state", - value: 0, - }, - startup_user_create_vars_ms: { - type: "gauge", - help: "Time spent running createVars", - value: 0, - }, - startup_user_on_wake_ms: { - type: "gauge", - help: "Time spent running onWake", - value: 0, - }, - startup_user_create_state_ms: { - type: "gauge", - help: "Time spent running createState", - value: 0, - }, - }; - }; - const actorCtx = makeActorCtx(ctx, jsRequest); try { if ( @@ -3591,12 +3496,6 @@ export function buildNativeFactory( workflowHistory: workflowHistory(), }); } - if ( - url.pathname === "/inspector/metrics" && - jsRequest.method === "GET" - ) { - return jsonResponse(metricsResponse(actorCtx)); - } if ( jsRequest.method === "POST" && url.pathname.startsWith("/inspector/action/") @@ -3662,9 +3561,14 @@ export function buildNativeFactory( const actorCtx = makeActorCtx(ctx); try { const decodedInput = decodeValue(input); + const startedAt = performance.now(); const state = hasStaticState ? structuredClone(config.state) : await config.createState(actorCtx, decodedInput); + logger().debug({ + msg: "perf user: createStateMs", + durationMs: performance.now() - startedAt, + }); actorCtx.initializeState(state); return encodeValue(state); } finally { @@ -3703,9 +3607,14 @@ export function buildNativeFactory( const { ctx } = unwrapTsfnPayload(error, payload); const actorCtx = makeActorCtx(ctx); try { + const startedAt = performance.now(); const vars = hasStaticVars ? structuredClone(config.vars) : await config.createVars(actorCtx, undefined); + logger().debug({ + msg: "perf user: createVarsMs", + durationMs: performance.now() - startedAt, + }); actorCtx.vars = vars; } finally { await actorCtx.dispose(); @@ -3756,7 +3665,12 @@ export function buildNativeFactory( const { ctx } = unwrapTsfnPayload(error, payload); const actorCtx = makeActorCtx(ctx); try { + const startedAt = performance.now(); await config.onWake(actorCtx); + logger().debug({ + msg: "perf user: onWakeMs", + durationMs: performance.now() - startedAt, + }); } finally { await actorCtx.dispose(); } @@ -4475,9 +4389,9 @@ export async function buildNativeRegistry(config: RegistryConfig): Promise<{ }> { if ( config.test?.enabled && - process.env.RIVET_INSPECTOR_TOKEN === undefined + process.env._RIVET_TEST_INSPECTOR_TOKEN === undefined ) { - process.env.RIVET_INSPECTOR_TOKEN = "token"; + process.env._RIVET_TEST_INSPECTOR_TOKEN = "token"; } const bindings = await loadNativeBindings();