Skip to main content

rivetkit_core/
lib.rs

1#[cfg(all(feature = "native-runtime", feature = "wasm-runtime"))]
2compile_error!(
3	"`native-runtime` and `wasm-runtime` are mutually exclusive. Enable exactly one rivetkit-core runtime."
4);
5
6pub mod actor;
7#[cfg(feature = "native-runtime")]
8mod development_process;
9#[cfg(feature = "native-runtime")]
10pub mod engine_process;
11pub mod error;
12pub mod inspector;
13pub mod inspector_bundle;
14pub mod metrics_endpoint;
15pub mod registry;
16pub mod runtime;
17pub(crate) mod serde_metrics;
18pub mod serverless;
19#[cfg(feature = "native-runtime")]
20pub mod serverless_http;
21#[cfg(feature = "native-runtime")]
22mod services_process;
23#[cfg(any(test, feature = "test-support"))]
24pub mod testing;
25pub(crate) mod time {
26	use std::fmt;
27	use std::future::Future;
28	use std::time::Duration;
29
30	#[cfg(target_arch = "wasm32")]
31	use futures::FutureExt;
32	#[cfg(target_arch = "wasm32")]
33	use wasm_bindgen::{JsCast, JsValue};
34	#[cfg(target_arch = "wasm32")]
35	use wasm_bindgen_futures::JsFuture;
36
37	#[cfg(not(target_arch = "wasm32"))]
38	pub use std::time::{Instant, SystemTime, UNIX_EPOCH};
39	#[cfg(target_arch = "wasm32")]
40	pub use web_time::{Instant, SystemTime, UNIX_EPOCH};
41
42	#[derive(Debug, Clone, Copy)]
43	pub struct TimeoutError;
44
45	impl fmt::Display for TimeoutError {
46		fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47			f.write_str("operation timed out")
48		}
49	}
50
51	impl std::error::Error for TimeoutError {}
52
53	#[cfg(not(target_arch = "wasm32"))]
54	pub fn tokio_deadline(deadline: Instant) -> tokio::time::Instant {
55		deadline.into()
56	}
57
58	#[cfg(target_arch = "wasm32")]
59	pub async fn sleep(duration: Duration) {
60		let delay_ms = duration.as_millis().min(u32::MAX as u128) as f64;
61		let promise = js_sys::Promise::new(&mut |resolve, _reject| {
62			let global = js_sys::global();
63			let set_timeout = js_sys::Reflect::get(&global, &JsValue::from_str("setTimeout"))
64				.ok()
65				.and_then(|value| value.dyn_into::<js_sys::Function>().ok());
66
67			if let Some(set_timeout) = set_timeout {
68				let _ = set_timeout.call2(&global, &resolve, &JsValue::from_f64(delay_ms));
69			} else {
70				let _ = resolve.call0(&JsValue::UNDEFINED);
71			}
72		});
73
74		let _ = JsFuture::from(promise).await;
75	}
76
77	#[cfg(not(target_arch = "wasm32"))]
78	pub async fn sleep(duration: Duration) {
79		tokio::time::sleep(duration).await;
80	}
81
82	#[cfg(not(target_arch = "wasm32"))]
83	pub async fn sleep_until(deadline: Instant) {
84		tokio::time::sleep_until(tokio_deadline(deadline)).await;
85	}
86
87	#[cfg(target_arch = "wasm32")]
88	pub async fn sleep_until(deadline: Instant) {
89		let remaining = deadline
90			.checked_duration_since(Instant::now())
91			.unwrap_or(Duration::ZERO);
92		sleep(remaining).await;
93	}
94
95	#[cfg(not(target_arch = "wasm32"))]
96	pub async fn timeout<F>(duration: Duration, future: F) -> Result<F::Output, TimeoutError>
97	where
98		F: Future,
99	{
100		tokio::time::timeout(duration, future)
101			.await
102			.map_err(|_| TimeoutError)
103	}
104
105	#[cfg(target_arch = "wasm32")]
106	pub async fn timeout<F>(duration: Duration, future: F) -> Result<F::Output, TimeoutError>
107	where
108		F: Future,
109	{
110		futures::pin_mut!(future);
111		let timer = sleep(duration);
112		futures::pin_mut!(timer);
113
114		futures::select! {
115			result = future.fuse() => Ok(result),
116			_ = timer.fuse() => Err(TimeoutError),
117		}
118	}
119}
120pub mod types;
121pub mod websocket;
122pub use actor::{kv, sqlite};
123
124pub use actor::action::ActionDispatchError;
125pub use actor::config::{
126	ActionDefinition, ActorConfig, ActorConfigInput, ActorConfigOverrides, CanHibernateWebSocket,
127	SqliteProfilingConfig, SqliteProfilingConfigInput,
128};
129pub use actor::connection::ConnHandle;
130pub use actor::context::{
131	ActorContext, ActorKv, ActorWorkRegion, KeepAwakeRegion, WebSocketCallbackRegion,
132};
133pub use actor::factory::{ActorEntryFn, ActorFactory};
134pub use actor::lifecycle_hooks::{ActorEvents, ActorStart, Reply};
135pub use actor::messages::{
136	ActorEvent, ActorHttpResponse, QueueSendResult, QueueSendStatus, Request, Response,
137	SerializeStateReason, StateDelta, StreamingResponse, WorkflowKvWrite,
138};
139pub use actor::queue::{
140	CompletableQueueMessage, EnqueueAndWaitOpts, QueueMessage, QueueNextBatchOpts, QueueNextOpts,
141	QueueTryNextBatchOpts, QueueTryNextOpts, QueueWaitOpts,
142};
143pub use actor::sqlite::{
144	BindParam, ColumnValue, ExecResult, ExecuteResult, QueryResult, SqliteBackend,
145	SqliteBatchStatement, SqliteDb, SqliteTransaction,
146};
147pub use actor::state::{ActorStateTransaction, RequestSaveOpts};
148pub use actor::task::{
149	ActionDispatchResult, ActorTask, DispatchCommand, HttpDispatchResult, LifecycleCommand,
150	LifecycleEvent, LifecycleState,
151};
152pub use actor::task_types::ShutdownKind;
153pub use actor::work_registry::{ActorWorkKind, ActorWorkPolicy};
154pub use error::ActorLifecycle;
155pub use inspector::{Inspector, InspectorSnapshot};
156pub use registry::{CoreRegistry, EngineSpawnMode, RuntimeMode, ServeConfig};
157pub use rivet_envoy_client::config::{
158	HTTP_BODY_MAX_CHUNK_SIZE, HTTP_BODY_STREAM_CHANNEL_CAPACITY, HttpRequestBodyStream,
159	ResponseChunk,
160};
161pub use runtime::{RuntimeBoxFuture, RuntimeSpawner, boxed_runtime_future};
162pub use serverless::{CoreServerlessRuntime, ServerlessRequest, ServerlessResponse};
163pub use types::{
164	ActorKey, ActorKeySegment, ConnId, ListOpts, SaveStateOpts, WsMessage, format_actor_key,
165};
166pub use websocket::WebSocket;