nexus_acto_rs/actor/
actor_system.rs1use std::sync::Arc;
2use std::time::Duration;
3
4use tokio::sync::Mutex;
5use uuid::Uuid;
6
7use crate::actor::actor::ExtendedPid;
8use crate::actor::actor::Pid;
9use crate::actor::context::RootContext;
10use crate::actor::dispatch::DeadLetterProcess;
11use crate::actor::event_stream::EventStreamProcess;
12use crate::actor::guardian::GuardiansValue;
13use crate::actor::message::EMPTY_MESSAGE_HEADER;
14use crate::actor::process::process_registry::ProcessRegistry;
15use crate::actor::process::ProcessHandle;
16use crate::actor::supervisor::subscribe_supervision;
17use crate::ctxext::extensions::ContextExtensions;
18use crate::event_stream::EventStream;
19
20#[derive(Debug, Clone)]
21struct ActorSystemInner {
22 process_registry: Option<ProcessRegistry>,
23 root_context: Option<RootContext>,
24 event_stream: Arc<EventStream>,
25 guardians: Option<GuardiansValue>,
26 dead_letter: Option<DeadLetterProcess>,
27 extensions: ContextExtensions,
28 config: Config,
29 id: String,
30}
31
32impl ActorSystemInner {
33 async fn new(config: Config) -> Self {
34 let id = Uuid::new_v4().to_string();
35 let myself = ActorSystemInner {
36 id: id.clone(),
37 config,
38 process_registry: None,
39 root_context: None,
40 guardians: None,
41 event_stream: Arc::new(EventStream::new()),
42 dead_letter: None,
45 extensions: ContextExtensions::new(),
46 };
47 myself
48 }
49}
50
51#[derive(Debug, Clone)]
52pub struct ActorSystem {
53 inner: Arc<Mutex<ActorSystemInner>>,
54}
55
56impl ActorSystem {
57 pub async fn new() -> Self {
58 Self::new_config_options([]).await
59 }
60
61 pub async fn new_config_options(options: impl IntoIterator<Item = ConfigOption>) -> Self {
62 let options = options.into_iter().collect::<Vec<_>>();
63 let config = Self::configure(options);
64 Self::new_with_config(config).await
65 }
66
67 pub async fn new_with_config(config: Config) -> Self {
68 let system = Self {
69 inner: Arc::new(Mutex::new(ActorSystemInner::new(config).await)),
70 };
71 system
72 .set_root_context(RootContext::new(system.clone(), EMPTY_MESSAGE_HEADER.clone(), &[]))
73 .await;
74 system.set_process_registry(ProcessRegistry::new(system.clone())).await;
75 system.set_guardians(GuardiansValue::new(system.clone())).await;
76 system
77 .set_dead_letter(DeadLetterProcess::new(system.clone()).await)
78 .await;
79
80 subscribe_supervision(&system).await;
81
82 let event_stream_process = ProcessHandle::new(EventStreamProcess::new(system.clone()));
87 system
88 .get_process_registry()
89 .await
90 .add_process(event_stream_process, "eventstream");
91
92 system
93 }
94
95 pub async fn new_local_pid(&self, id: &str) -> ExtendedPid {
96 let pr = self.get_process_registry().await;
97 let pid = Pid {
98 id: id.to_string(),
99 address: pr.get_address(),
100 request_id: 0,
101 };
102 ExtendedPid::new(pid, self.clone())
103 }
104
105 pub async fn get_address(&self) -> String {
110 self.get_process_registry().await.get_address()
111 }
112
113 pub async fn get_config(&self) -> Config {
114 let inner_mg = self.inner.lock().await;
115 inner_mg.config.clone()
116 }
117
118 pub async fn get_root_context(&self) -> RootContext {
119 let inner_mg = self.inner.lock().await;
120 inner_mg.root_context.as_ref().unwrap().clone()
121 }
122
123 pub async fn get_dead_letter(&self) -> ProcessHandle {
124 let inner_mg = self.inner.lock().await;
125 let dead_letter = inner_mg.dead_letter.as_ref().unwrap().clone();
126 ProcessHandle::new(dead_letter)
127 }
128
129 pub async fn get_process_registry(&self) -> ProcessRegistry {
130 let inner_mg = self.inner.lock().await;
131 inner_mg.process_registry.as_ref().unwrap().clone()
132 }
133
134 pub async fn get_event_stream(&self) -> Arc<EventStream> {
135 let inner_mg = self.inner.lock().await;
136 inner_mg.event_stream.clone()
137 }
138
139 pub async fn get_guardians(&self) -> GuardiansValue {
140 let inner_mg = self.inner.lock().await;
141 inner_mg.guardians.as_ref().unwrap().clone()
142 }
143
144 fn configure(options: Vec<ConfigOption>) -> Config {
145 let mut config = Config::default();
146 for option in options {
147 option.apply(&mut config);
148 }
149 config
150 }
151
152 async fn set_root_context(&self, root: RootContext) {
153 let mut inner_mg = self.inner.lock().await;
154 inner_mg.root_context = Some(root);
155 }
156
157 async fn set_process_registry(&self, process_registry: ProcessRegistry) {
158 let mut inner_mg = self.inner.lock().await;
159 inner_mg.process_registry = Some(process_registry);
160 }
161
162 async fn set_guardians(&self, guardians: GuardiansValue) {
163 let mut inner_mg = self.inner.lock().await;
164 inner_mg.guardians = Some(guardians);
165 }
166
167 async fn set_dead_letter(&self, dead_letter: DeadLetterProcess) {
168 let mut inner_mg = self.inner.lock().await;
169 inner_mg.dead_letter = Some(dead_letter);
170 }
171}
172
173#[derive(Debug, Clone)]
174pub struct Config {
175 pub log_prefix: String,
177 pub dispatcher_throughput: usize,
178 pub dead_letter_throttle_interval: Duration,
179 pub dead_letter_throttle_count: usize,
180 pub dead_letter_request_logging: bool,
181 pub developer_supervision_logging: bool,
182 }
184
185impl Default for Config {
186 fn default() -> Self {
187 Config {
188 log_prefix: "".to_string(),
190 dispatcher_throughput: 300,
191 dead_letter_throttle_interval: Duration::from_secs(1),
192 dead_letter_throttle_count: 10,
193 dead_letter_request_logging: false,
194 developer_supervision_logging: false,
195 }
197 }
198}
199
200pub enum ConfigOption {
201 SetLogPrefix(String),
203 SetDispatcherThroughput(usize),
204 SetDeadLetterThrottleInterval(Duration),
205 SetDeadLetterThrottleCount(usize),
206 }
208
209impl ConfigOption {
210 fn apply(&self, config: &mut Config) {
211 match self {
212 ConfigOption::SetLogPrefix(prefix) => {
216 config.log_prefix = prefix.clone();
217 }
218 ConfigOption::SetDispatcherThroughput(throughput) => {
219 config.dispatcher_throughput = *throughput;
220 }
221 ConfigOption::SetDeadLetterThrottleInterval(interval) => {
222 config.dead_letter_throttle_interval = *interval;
223 }
224 ConfigOption::SetDeadLetterThrottleCount(count) => {
225 config.dead_letter_throttle_count = *count;
226 } }
228 }
229}