pub trait Actor: Send + 'static {
type Error: Send + Debug + 'static;
// Provided methods
fn on_start(
&mut self,
_actor_ref: &ActorRef,
) -> impl Future<Output = Result<(), Self::Error>> + Send { ... }
fn on_stop(
&mut self,
_actor_ref: &ActorRef,
_stop_reason: &ActorStopReason,
) -> impl Future<Output = Result<(), Self::Error>> + Send { ... }
fn run_loop(
&mut self,
_actor_ref: &ActorRef,
) -> impl Future<Output = Result<(), Self::Error>> + Send { ... }
}Expand description
Defines the behavior of an actor.
Actors are fundamental units of computation that communicate by exchanging messages. Each actor has its own state and processes messages sequentially.
Implementors of this trait must also be Send + 'static.
Required Associated Types§
Provided Methods§
Sourcefn on_start(
&mut self,
_actor_ref: &ActorRef,
) -> impl Future<Output = Result<(), Self::Error>> + Send
fn on_start( &mut self, _actor_ref: &ActorRef, ) -> impl Future<Output = Result<(), Self::Error>> + Send
Called when the actor is started. This is optional and has a default implementation.
The actor_ref parameter is a reference to the actor’s own ActorRef.
This method can be used for initialization tasks.
If it returns an error, the actor will fail to start, and on_stop will be called
with an ActorStopReason::Error.
Sourcefn on_stop(
&mut self,
_actor_ref: &ActorRef,
_stop_reason: &ActorStopReason,
) -> impl Future<Output = Result<(), Self::Error>> + Send
fn on_stop( &mut self, _actor_ref: &ActorRef, _stop_reason: &ActorStopReason, ) -> impl Future<Output = Result<(), Self::Error>> + Send
Called when the actor is stopped. This is optional and has a default implementation.
The actor_ref parameter is a reference to the actor’s own ActorRef.
The stop_reason parameter indicates why the actor is stopping.
This method can be used for cleanup tasks.
Sourcefn run_loop(
&mut self,
_actor_ref: &ActorRef,
) -> impl Future<Output = Result<(), Self::Error>> + Send
fn run_loop( &mut self, _actor_ref: &ActorRef, ) -> impl Future<Output = Result<(), Self::Error>> + Send
The main execution loop for the actor.
This method is called after on_start and is expected to contain the primary logic
of the actor. It typically runs for the entire lifetime of the actor. The run_loop
method provides a dedicated task execution environment for executing custom logic,
while the framework manages the underlying execution details. It executes concurrently with message
handling, allowing actors to perform background work while remaining responsive to incoming messages.
§Key characteristics:
-
Continuous Processing: Ideal for implementing long-running tasks or periodic work that should execute throughout the actor’s lifetime.
-
Integration with Message Handling: While
run_loopis running, the actor will continue to process messages from its mailbox normally. -
State Access: Has full access to the actor’s state (
self) and can modify it, with changes visible to message handlers and vice versa. -
Required Await Points: Must include at least one
.awaitpoint inside any loop structure to yield control to the Tokio runtime. Without these await points, the actor will be unable to process incoming messages as task switching won’t occur. This is critical for the cooperative multitasking model that enables concurrent message processing.
§Common patterns:
-
Periodic tasks: For executing work at regular intervals
async fn run_loop(&mut self, _actor_ref: &ActorRef) -> Result<(), Self::Error> { let mut interval = tokio::time::interval(Duration::from_secs(5)); loop { interval.tick().await; // Critical await point enables message processing // Perform periodic task here // If your task is computationally intensive, ensure you still have an await: if self.heavy_computation_needed() { tokio::task::yield_now().await; // Explicitly yield to allow message processing } } } -
Handling blocking work: For CPU-intensive or I/O blocking operations
async fn run_loop(&mut self, _actor_ref: &ActorRef) -> Result<(), Self::Error> { loop { // IMPORTANT: Every loop iteration must have at least one await point // to ensure the actor can process incoming messages // Offload blocking operations to Tokio's blocking threadpool let result = tokio::task::spawn_blocking(|| { // CPU-bound or blocking I/O work here "computation result" }).await?; // This await allows message processing while computation runs // Process the result println!("Got result: {}", result); tokio::time::sleep(std::time::Duration::from_secs(1)).await; // Another await point } }
§Termination:
The run_loop method can trigger actor termination in two ways:
- Return
Ok(())for normal termination - Return
Err(_)to indicate an error condition
Any active loops must be cleanly broken for the method to return. Actors can maintain a
running flag that can be toggled by message handlers to signal termination.
The actor_ref parameter is a reference to the actor’s own ActorRef.
If this method returns Ok(()) or Err(_), the actor will be stopped.
If it returns Ok(()), on_stop will be called with ActorStopReason::Normal.
If it returns Err(_), on_stop will be called with ActorStopReason::Error.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.