maiko/actor.rs
1use core::marker::Send;
2use std::future::Future;
3
4use crate::{Envelope, Error, Event, Result, StepAction};
5
6/// Core trait implemented by user-defined actors.
7///
8/// Actors are independent units that encapsulate state and process events sequentially.
9/// Each actor has its own mailbox (channel) and processes one event at a time,
10/// eliminating the need for locks or shared state synchronization.
11///
12/// # Core Methods
13///
14/// - [`handle_event`](Self::handle_event) - Process incoming events (reactive)
15/// - [`step`](Self::step) - Perform periodic work or produce events (proactive)
16///
17/// # Lifecycle Hooks
18///
19/// - [`on_start`](Self::on_start) - Called once before the event loop starts
20/// - [`on_shutdown`](Self::on_shutdown) - Called once after the event loop stops
21/// - [`on_error`](Self::on_error) - Handle errors (swallow or propagate)
22///
23/// # Context (Optional)
24///
25/// Actors that need to send events or stop themselves should store a [`Context<E>`](crate::Context)
26/// received from their factory function. Pure event consumers don't need context:
27///
28/// ```ignore
29/// // Pure consumer - no context needed
30/// struct Logger;
31/// impl Actor for Logger { /* ... */ }
32///
33/// // Producer - stores context to send events
34/// struct Producer { ctx: Context<MyEvent> }
35/// ```
36///
37/// # Ergonomics
38///
39/// Methods return futures but can be implemented as `async fn` directly.
40/// No `#[async_trait]` macro is required.
41///
42/// See also: [`Context`](crate::Context), [`Supervisor`](crate::Supervisor), [`Envelope`](crate::Envelope).
43pub trait Actor: Send + 'static {
44 type Event: Event + Send;
45
46 /// Handle a single incoming event.
47 ///
48 /// Receives the full [`Envelope`] containing both the event payload and metadata.
49 /// Use `envelope.event()` for pattern matching, or access `envelope.meta` for
50 /// sender information and correlation IDs.
51 ///
52 /// # Example
53 ///
54 /// ```ignore
55 /// async fn handle_event(&mut self, envelope: &Envelope<Self::Event>) -> Result<()> {
56 /// match envelope.event() {
57 /// MyEvent::Foo(x) => self.handle_foo(x).await,
58 /// MyEvent::Bar => {
59 /// // Access metadata when needed
60 /// println!("Bar from {}", envelope.meta.actor_name());
61 /// Ok(())
62 /// }
63 /// }
64 /// }
65 /// ```
66 ///
67 /// Called for every event routed to this actor. Return `Ok(())` when
68 /// processing succeeds, or an error to signal failure. Use `Context::send`
69 /// to emit follow-up events as needed.
70 fn handle_event(
71 &mut self,
72 envelope: &Envelope<Self::Event>,
73 ) -> impl Future<Output = Result<()>> + Send {
74 let _ = envelope;
75 async { Ok(()) }
76 }
77
78 /// Optional periodic work or event production.
79 ///
80 /// Returns a [`StepAction`] to control when `step` runs again:
81 ///
82 /// | Action | Behavior |
83 /// |--------|----------|
84 /// | `StepAction::Continue` | Run step again immediately |
85 /// | `StepAction::Yield` | Yield to runtime, then run again |
86 /// | `StepAction::AwaitEvent` | Pause until next event arrives |
87 /// | `StepAction::Backoff(Duration)` | Sleep, then run again |
88 /// | `StepAction::Never` | Disable step permanently (default) |
89 ///
90 /// # Common Patterns
91 ///
92 /// **Time-Based Producer** (polls periodically):
93 /// ```rust,ignore
94 /// async fn step(&mut self) -> Result<StepAction> {
95 /// self.ctx.send(HeartbeatEvent).await?;
96 /// Ok(StepAction::Backoff(Duration::from_secs(5)))
97 /// }
98 /// ```
99 ///
100 /// **External Event Source** (driven by I/O):
101 /// ```rust,ignore
102 /// async fn step(&mut self) -> Result<StepAction> {
103 /// let frame = self.websocket.read().await?;
104 /// self.ctx.send(WebSocketEvent(frame)).await?;
105 /// Ok(StepAction::Continue)
106 /// }
107 /// ```
108 ///
109 /// **Pure Event Processor** (no step logic needed):
110 /// ```rust,ignore
111 /// async fn step(&mut self) -> Result<StepAction> {
112 /// Ok(StepAction::Never) // Default behavior
113 /// }
114 /// ```
115 ///
116 /// # Default Behavior
117 ///
118 /// Returns `StepAction::Never`, making the actor purely event-driven.
119 fn step(&mut self) -> impl Future<Output = Result<StepAction>> + Send {
120 async { Ok(StepAction::Never) }
121 }
122
123 /// Lifecycle hook called once before the event loop starts.
124 ///
125 /// Equivalent to:
126 ///
127 /// ```ignore
128 /// async fn on_start(&mut self) -> Result<()>;
129 /// ```
130 fn on_start(&mut self) -> impl Future<Output = Result<()>> + Send {
131 async { Ok(()) }
132 }
133
134 /// Lifecycle hook called once after the event loop stops.
135 ///
136 /// Equivalent to:
137 ///
138 /// ```ignore
139 /// async fn on_shutdown(&mut self) -> Result<()>;
140 /// ```
141 fn on_shutdown(&mut self) -> impl Future<Output = Result<()>> + Send {
142 async { Ok(()) }
143 }
144
145 /// Called when an error is returned by [`handle_event`](Self::handle_event) or [`step`](Self::step).
146 ///
147 /// Return `Ok(())` to swallow the error and continue processing,
148 /// or `Err(error)` to propagate and stop the actor.
149 ///
150 /// # Default Behavior
151 ///
152 /// By default, all errors propagate (actor stops). Override this to implement
153 /// custom error handling, logging, or recovery logic.
154 ///
155 /// # Example
156 ///
157 /// ```rust
158 /// use maiko::{Actor, Error, Event, Result};
159 /// # #[derive(Clone, Event)]
160 /// # struct MyEvent;
161 /// # struct MyActor;
162 /// # impl Actor for MyActor {
163 /// # type Event = MyEvent;
164 /// fn on_error(&self, error: Error) -> Result<()> {
165 /// eprintln!("Actor error: {}", error);
166 /// Ok(()) // Swallow and continue
167 /// }
168 /// # }
169 /// ```
170 fn on_error(&self, error: Error) -> Result<()> {
171 Err(error)
172 }
173}