Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions rivetkit-typescript/packages/rivetkit-napi/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* tslint:disable */

Check failure on line 1 in rivetkit-typescript/packages/rivetkit-napi/index.d.ts

View workflow job for this annotation

GitHub Actions / RivetKit / Quality Check

format

Formatter would have printed the following content:
/* eslint-disable */

/* auto-generated by NAPI-RS */
Expand Down Expand Up @@ -50,6 +50,7 @@
export interface JsActorConfig {
name?: string
icon?: string
hasDatabase?: boolean
canHibernateWebsocket?: boolean
stateSaveIntervalMs?: number
createStateTimeoutMs?: number
Expand Down
18 changes: 17 additions & 1 deletion rivetkit-typescript/packages/rivetkit-napi/src/actor_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -766,14 +766,30 @@ impl ActorContextShared {
*self.abort_token.lock() = None;
*self.run_restart.lock() = None;
*self.task_sender.lock() = None;
*self.runtime_state.lock() = None;
// napi Ref::unref requires an Env; this function runs on tokio workers
// with no Env available. Dropping without unref panics a debug_assert in
// napi-rs and silently leaks the napi reference slot in release. Forget
// instead so debug matches release behavior. Leak is bounded to one
// JsObject per actor wake cycle until the process exits.
if let Some(old) = self.runtime_state.lock().take() {
std::mem::forget(old);
}
*self.end_reason.lock() = None;
*self.websocket_callback_regions.lock() = BTreeMap::new();
self.next_websocket_callback_region_id
.store(0, Ordering::SeqCst);
}
}

impl Drop for ActorContextShared {
fn drop(&mut self) {
// Same Env-less drop problem as reset_runtime_state. See comment there.
if let Some(old) = self.runtime_state.lock().take() {
std::mem::forget(old);
}
}
}

fn actor_context_shared(actor_id: &str) -> Arc<ActorContextShared> {
ACTOR_CONTEXT_SHARED.retain_sync(|_, shared| shared.strong_count() > 0);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ pub struct JsActionDefinition {
pub struct JsActorConfig {
pub name: Option<String>,
pub icon: Option<String>,
pub has_database: Option<bool>,
pub can_hibernate_websocket: Option<bool>,
pub state_save_interval_ms: Option<u32>,
pub create_state_timeout_ms: Option<u32>,
Expand Down Expand Up @@ -883,7 +884,6 @@ fn build_action_payload(env: &Env, payload: ActionPayload) -> napi::Result<Vec<n
Some(conn) => object.set("conn", ConnHandle::new(conn))?,
None => object.set("conn", env.get_null()?)?,
}
object.set("name", payload.name)?;
object.set("args", Buffer::from(payload.args))?;
match payload.cancel_token {
Some(cancel_token) => object.set("cancelToken", CancellationToken::new(cancel_token))?,
Expand Down Expand Up @@ -929,7 +929,7 @@ fn build_serialize_state_payload(
) -> napi::Result<Vec<napi::JsUnknown>> {
let mut object = env.create_object()?;
object.set("ctx", ActorContext::new(payload.ctx))?;
object.set("reason", payload.reason)?;
object.set("reason", env.create_string_from_std(payload.reason)?)?;
Ok(vec![object.into_unknown()])
}

Expand Down Expand Up @@ -1035,6 +1035,7 @@ impl From<JsActorConfig> for ActorConfigInput {
Self {
name: value.name,
icon: value.icon,
has_database: value.has_database,
can_hibernate_websocket: value.can_hibernate_websocket,
state_save_interval_ms: value.state_save_interval_ms,
create_vars_timeout_ms: value.create_vars_timeout_ms,
Expand Down
3 changes: 2 additions & 1 deletion rivetkit-typescript/packages/rivetkit/src/registry/native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ type NativeWebSocketWithEvents = NativeWebSocket & {
};
const textEncoder = new TextEncoder();
const textDecoder = new TextDecoder();
type SerializeStateReason = "save" | "inspector" | "sleep" | "destroy";
type SerializeStateReason = "save" | "inspector";
type NativeOnStateChangeHandler = (
ctx: NativeActorContextAdapter,
state: unknown,
Expand Down Expand Up @@ -3046,6 +3046,7 @@ function buildActorConfig(
return {
name: options.name as string | undefined,
icon: options.icon as string | undefined,
hasDatabase: config.db !== undefined,
canHibernateWebsocket:
typeof canHibernate === "boolean" ? canHibernate : undefined,
stateSaveIntervalMs: options.stateSaveInterval as number | undefined,
Expand Down
Loading