1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
//! A pure-Rust actor framework built on top of the [Tokio](https://tokio.rs) async runtime,
//! inspired by Alice Ryhl's [Actors with Tokio](https://ryhl.io/blog/actors-with-tokio/).
//!
//! `acktor` builds on the patterns described in Alice Ryhl's blog post and extends them into a
//! structured library. Each actor runs as an independent `tokio` task with its own mailbox,
//! processing messages one at a time. Actors communicate exclusively through message passing —
//! there is no shared mutable state. The framework provides lifecycle hooks, supervision, an
//! observer pattern, and support for periodic tasks.
//!
//! # Quick Start
//!
//! An example `Counter` actor that handles arithmetic messages might be the following:
//!
//! ```rust
//! use acktor::{Actor, Context, Handler, Message, Signal};
//!
//! #[derive(Debug)]
//! struct Counter(i64);
//!
//! impl Actor for Counter {
//! type Context = Context<Self>;
//! type Error = String;
//! }
//!
//! #[derive(Debug)]
//! enum CounterMsg {
//! Increment,
//! Get,
//! }
//!
//! impl Message for CounterMsg {
//! type Result = i64;
//! }
//!
//! impl Handler<CounterMsg> for Counter {
//! type Result = i64;
//!
//! async fn handle(&mut self, msg: CounterMsg, _ctx: &mut Self::Context) -> i64 {
//! match msg {
//! CounterMsg::Increment => self.0 += 1,
//! CounterMsg::Get => {}
//! }
//! self.0
//! }
//! }
//!
//! async fn start() {
//! let (addr, handle) = Counter(0).start("counter").unwrap();
//!
//! // fire-and-forget
//! addr.do_send(CounterMsg::Increment).await.unwrap();
//!
//! // request-reply
//! let result = addr.send(CounterMsg::Get).await.unwrap().await.unwrap();
//! println!("Counter: {result}"); // Counter: 1
//!
//! addr.do_send(Signal::Stop).await.unwrap();
//! handle.await.unwrap();
//! }
//! ```
//!
//! # Supervision
//!
//! Implement `Handler<SupervisionEvent<A>>` on the supervisor actor. Use the command
//! [`Supervisor::Set`][supervisor::Supervisor::Set] to attach the supervisor actor to the child
//! (or [`Supervisor::Unset`][supervisor::Supervisor::Unset] to detach). Since every actor handles
//! `Supervisor<A>` automatically, no extra wiring is needed on the child side.
//!
//! ```ignore
//! use acktor::{Actor, Context, Handler, supervisor::SupervisionEvent};
//!
//! struct Worker;
//!
//! impl Actor for Worker {
//! type Context = Context<Self>;
//! type Error = String;
//! }
//!
//! #[derive(Default)]
//! struct Watchdog;
//!
//! impl Actor for Watchdog {
//! type Context = Context<Self>;
//! type Error = String;
//! }
//!
//! impl Handler<SupervisionEvent<Worker>> for Watchdog {
//! type Result = ();
//!
//! async fn handle(&mut self, event: SupervisionEvent<Worker>, _ctx: &mut Self::Context) {
//! println!("worker event: {:?}", event);
//! }
//! }
//! ```
//!
//! # Observer
//!
//! For a subject actor, implement the [`SubjectActor<Event>`][observer::SubjectActor] trait so it
//! can emit `Event`s to registered observers. Every subject actor automatically gets a
//! `Handler<Observer<Event>>` implementation that manages the observers, so the observers can be
//! registered by sending [`Observer::Register`][observer::Observer::Register] commands to the
//! subject actor (or [`Observer::Unregister`][observer::Observer::Unregister] to stop receiving
//! events).
//!
//! ```ignore
//! use acktor::{Actor, Context, Message, observer::{ObserverSet, SubjectActor}};
//!
//! #[derive(Clone, Message)]
//! #[result_type(())]
//! struct Tick;
//!
//! #[derive(Default)]
//! struct Clock { observers: ObserverSet<Tick> }
//!
//! impl Actor for Clock {
//! type Context = Context<Self>;
//! type Error = String;
//! }
//!
//! impl SubjectActor<Tick> for Clock {
//! fn observers_mut(&mut self) -> &mut ObserverSet<Tick> { &mut self.observers }
//! }
//! ```
//!
//! # Cron Tasks
//!
//! Use [`CronContext<Self>`][cron::CronContext] as the actor's context and implement
//! [`CronActor`][cron::CronActor] trait to opt in this feature. `CronActor` trait defines a
//! `task` method that is invoked repeatedly with a delay determined by its return value.
//!
//! ```ignore
//! use std::time::Duration;
//! use acktor::{Actor, cron::{CronActor, CronContext}};
//!
//! struct Heartbeat;
//!
//! impl Actor for Heartbeat {
//! type Context = CronContext<Self>;
//! type Error = String;
//! }
//!
//! impl CronActor for Heartbeat {
//! async fn task(&mut self, _ctx: &mut Self::Context) -> Result<Duration, Self::Error> {
//! println!("tick");
//! Ok(Duration::from_secs(1))
//! }
//! }
//! ```
//!
//! # Feature Flags
//!
//! | Feature | Default | Description |
//! |---------|---------|-------------|
//! | `derive` | Yes | Re-exports the derive macros from [`acktor-derive`](https://docs.rs/acktor-derive). |
//! | `observer` | Yes | Enables the [`observer`] module. |
//! | `cron` | Yes | Enables the [`cron`] module. |
//! | `identifier` | No | Enables stable type identifiers ([`stable_type_id`], [`MessageId`]). |
//! | `ipc` | No | Enables IPC support: the [`codec`] module, [`BinaryMessage`][message::BinaryMessage], remote addressing ([`RemoteAddressable`], [`RemoteSpawnable`], [`RemoteProxy`]), and the `proto` re-export. Implies `identifier`. |
//! | `prost-codec` | No | Use an all-prost primitive codec instead of the default zerocopy + prost mix (useful for cross-language interop). |
//! | `bottleneck-warning` | No | Emits `tracing::debug!` logs when an observer's mailbox is full during notification, useful for spotting slow consumers. |
//! | `tokio-tracing` | No | Names spawned actor tasks for [`tokio-console`](https://docs.rs/console-subscriber). Requires building with `RUSTFLAGS="--cfg tokio_unstable"`. |
//!
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use RemoteProxy;
pub use ;
pub use MessageId;
pub use ;
pub use Signal;
pub use ;
pub use ;
pub use ;
/// Re-export the IPC protocol definitions for convenience.
pub use acktor_ipc_proto as proto;
// re-export for use in derived code
pub use bytes;
pub use sha2_const;
pub use tracing;
pub use test_utils;