Skip to main content

rivetkit_core/actor/
factory.rs

1use std::fmt;
2
3use anyhow::Result;
4
5use crate::ActorConfig;
6use crate::actor::lifecycle_hooks::ActorStart;
7use crate::runtime::RuntimeBoxFuture;
8
9#[cfg(feature = "wasm-runtime")]
10pub type ActorEntryFn = dyn Fn(ActorStart) -> RuntimeBoxFuture<Result<()>>;
11
12#[cfg(not(feature = "wasm-runtime"))]
13pub type ActorEntryFn = dyn Fn(ActorStart) -> RuntimeBoxFuture<Result<()>> + Send + Sync;
14
15/// Runtime extension point for building actor receive loops.
16pub struct ActorFactory {
17	config: ActorConfig,
18	entry: Box<ActorEntryFn>,
19	manual_startup_ready: bool,
20	streams_request_body: bool,
21}
22
23#[cfg(feature = "wasm-runtime")]
24unsafe impl Send for ActorFactory {}
25
26#[cfg(feature = "wasm-runtime")]
27unsafe impl Sync for ActorFactory {}
28
29impl ActorFactory {
30	pub fn new<F>(config: ActorConfig, entry: F) -> Self
31	where
32		F: ActorEntry,
33	{
34		Self {
35			config,
36			entry: Box::new(entry),
37			manual_startup_ready: false,
38			streams_request_body: false,
39		}
40	}
41
42	/// Builds a factory whose runtime will explicitly signal `startup_ready`
43	/// after its own startup preamble finishes.
44	pub fn new_with_manual_startup_ready<F>(config: ActorConfig, entry: F) -> Self
45	where
46		F: ActorEntry,
47	{
48		Self {
49			config,
50			entry: Box::new(entry),
51			manual_startup_ready: true,
52			streams_request_body: false,
53		}
54	}
55
56	/// Declares that this runtime consumes request bodies incrementally.
57	pub fn with_streaming_request_body(mut self) -> Self {
58		self.streams_request_body = true;
59		self
60	}
61
62	pub fn config(&self) -> &ActorConfig {
63		&self.config
64	}
65
66	pub(crate) fn requires_manual_startup_ready(&self) -> bool {
67		self.manual_startup_ready
68	}
69
70	pub(crate) fn streams_request_body(&self) -> bool {
71		self.streams_request_body
72	}
73
74	pub async fn start(&self, start: ActorStart) -> Result<()> {
75		(self.entry)(start).await
76	}
77}
78
79#[cfg(feature = "wasm-runtime")]
80pub trait ActorEntry: Fn(ActorStart) -> RuntimeBoxFuture<Result<()>> + 'static {}
81
82#[cfg(feature = "wasm-runtime")]
83impl<F> ActorEntry for F where F: Fn(ActorStart) -> RuntimeBoxFuture<Result<()>> + 'static {}
84
85#[cfg(not(feature = "wasm-runtime"))]
86pub trait ActorEntry:
87	Fn(ActorStart) -> RuntimeBoxFuture<Result<()>> + Send + Sync + 'static
88{
89}
90
91#[cfg(not(feature = "wasm-runtime"))]
92impl<F> ActorEntry for F where
93	F: Fn(ActorStart) -> RuntimeBoxFuture<Result<()>> + Send + Sync + 'static
94{
95}
96
97impl fmt::Debug for ActorFactory {
98	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
99		f.debug_struct("ActorFactory")
100			.field("config", &self.config)
101			.field("manual_startup_ready", &self.manual_startup_ready)
102			.field("streams_request_body", &self.streams_request_body)
103			.field("entry", &"<boxed entry>")
104			.finish()
105	}
106}