Skip to main content

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}