pub struct ActorRef<T: Actor> { /* private fields */ }Expand description
A type-safe reference to an actor of type T.
ActorRef<T> provides type-safe message passing to actors, ensuring that only
messages that the actor can handle are sent, and that reply types are correctly typed.
It provides compile-time type safety through Rust’s type system and trait bounds.
§Type Safety Benefits
- Compile-Time Message Validation: Only messages implementing
Message<M>for actorTare accepted - Automatic Reply Type Inference: Return types are inferred from trait implementations
- Zero Runtime Overhead: Type safety is enforced at compile time with no performance cost
- IDE Support: Full autocomplete and type checking support
- Prevention of Runtime Type Errors: Eliminates downcasting failures and type mismatches
§Message Passing Methods
-
Asynchronous Methods:
ask: Send a message and await a typed reply.ask_with_timeout: Send a message and await a typed reply with a timeout.tell: Send a message without waiting for a reply.tell_with_timeout: Send a message without waiting for a reply with a timeout.
-
Blocking Methods:
blocking_ask: Send a message and block until a typed reply is received (no runtime context required).blocking_tell: Send a message and block until it is sent (no runtime context required).ask_blocking: (Deprecated) Send a message and block until a typed reply is received.tell_blocking: (Deprecated) Send a message and block until it is sent.
The new
blocking_*methods use Tokio’s underlyingblocking_sendandblocking_recvand can be used from any thread. -
Control Methods:
-
Utility Methods:
§Recommended Usage
Use ActorRef<T> by default for all actor communication. It provides compile-time
guarantees that prevent type-related runtime errors.
When to use ActorRef<T>:
- Default choice for actor communication
- When you know the actor type at compile time
- When you want compile-time message validation
- When working with strongly-typed actor systems
Implementations§
Source§impl<T: Actor> ActorRef<T>
impl<T: Actor> ActorRef<T>
Sourcepub fn is_alive(&self) -> bool
pub fn is_alive(&self) -> bool
Checks if the actor is still alive by verifying if its channels are open.
Sourcepub fn downgrade(this: &Self) -> ActorWeak<T>
pub fn downgrade(this: &Self) -> ActorWeak<T>
Creates a weak, type-safe reference to this actor.
The returned ActorWeak<T> can be used to check if the actor is still alive
and optionally upgrade back to a strong ActorRef<T> without keeping the actor alive.
When the metrics feature is enabled, metrics are preserved via strong reference
for post-mortem analysis.
Sourcepub async fn tell<M>(&self, msg: M) -> Result<()>
pub async fn tell<M>(&self, msg: M) -> Result<()>
Sends a message to the actor without awaiting a reply (fire-and-forget).
The message is sent to the actor’s mailbox for processing. This method returns immediately.
Type safety: Only messages that the actor T can handle via Message<M> trait are accepted.
Sourcepub async fn tell_with_timeout<M>(
&self,
msg: M,
timeout: Duration,
) -> Result<()>
pub async fn tell_with_timeout<M>( &self, msg: M, timeout: Duration, ) -> Result<()>
Sends a message to the actor without awaiting a reply (fire-and-forget) with a timeout.
Similar to ActorRef::tell, but allows specifying a timeout for the send operation.
The message is sent to the actor’s mailbox, and this method will return once
the message is sent or timeout if the send operation doesn’t complete
within the specified duration.
Sourcepub async fn ask<M>(&self, msg: M) -> Result<T::Reply>
pub async fn ask<M>(&self, msg: M) -> Result<T::Reply>
Sends a message to the actor and awaits a reply.
The message is sent to the actor’s mailbox, and this method will wait for the actor to process the message and send a reply.
Type safety: The return type R is automatically inferred from the Message<M> trait
implementation, ensuring compile-time type safety for replies.
Sourcepub async fn ask_with_timeout<M>(
&self,
msg: M,
timeout: Duration,
) -> Result<T::Reply>
pub async fn ask_with_timeout<M>( &self, msg: M, timeout: Duration, ) -> Result<T::Reply>
Sends a message to the actor and awaits a reply with a timeout.
Similar to ActorRef::ask, but allows specifying a timeout for the operation.
The message is sent to the actor’s mailbox, and this method will wait for
the actor to process the message and send a reply, or timeout if the reply
doesn’t arrive within the specified duration.
Sourcepub fn kill(&self) -> Result<()>
pub fn kill(&self) -> Result<()>
Sends an immediate termination signal to the actor.
The actor will stop processing messages and shut down as soon as possible. The actor’s final result will indicate it was killed.
Sourcepub async fn stop(&self) -> Result<()>
pub async fn stop(&self) -> Result<()>
Sends a graceful stop signal to the actor.
The actor will process all messages currently in its mailbox and then stop. New messages sent after this call might be ignored or fail. The actor’s final result will indicate normal completion.
Sourcepub fn blocking_tell<M>(&self, msg: M, timeout: Option<Duration>) -> Result<()>
pub fn blocking_tell<M>(&self, msg: M, timeout: Option<Duration>) -> Result<()>
Synchronous version of ActorRef::tell that blocks until the message is sent.
This method can be used from any thread, including non-async contexts. It does not require a Tokio runtime context.
§Timeout Behavior
-
timeout: None: Uses Tokio’sblocking_senddirectly. This is the most efficient option but will block indefinitely if the mailbox is full. -
timeout: Some(duration): Spawns a separate thread with a temporary Tokio runtime to handle the timeout. This approach has additional overhead but guarantees the call will return within the specified duration.
§Performance Considerations
When using a timeout, this method incurs the following overhead:
- Thread creation: ~50-200μs depending on the platform
- Tokio runtime creation: ~1-10μs for a single-threaded runtime
- Channel synchronization: Minimal overhead for result passing
For performance-critical code paths where timeout is not required, pass None to avoid
this overhead. The timeout variant is designed for scenarios where bounded waiting is
more important than raw performance.
§Thread Safety
This method is safe to call from within an existing Tokio runtime context because the timeout implementation spawns a separate thread with its own runtime, avoiding the “cannot start a runtime from within a runtime” panic.
Sourcepub fn blocking_ask<M>(
&self,
msg: M,
timeout: Option<Duration>,
) -> Result<T::Reply>
pub fn blocking_ask<M>( &self, msg: M, timeout: Option<Duration>, ) -> Result<T::Reply>
Synchronous version of ActorRef::ask that blocks until the reply is received.
This method can be used from any thread, including non-async contexts. It does not require a Tokio runtime context.
§Timeout Behavior
-
timeout: None: Uses Tokio’sblocking_sendandblocking_recvdirectly. This is the most efficient option but will block indefinitely if the actor never responds. -
timeout: Some(duration): Spawns a separate thread with a temporary Tokio runtime to handle the timeout. This approach has additional overhead but guarantees the call will return within the specified duration.
§Performance Considerations
When using a timeout, this method incurs the following overhead:
- Thread creation: ~50-200μs depending on the platform
- Tokio runtime creation: ~1-10μs for a single-threaded runtime
- Channel synchronization: Minimal overhead for result passing
For performance-critical code paths where timeout is not required, pass None to avoid
this overhead. The timeout variant is designed for scenarios where bounded waiting is
more important than raw performance.
§Thread Safety
This method is safe to call from within an existing Tokio runtime context because the timeout implementation spawns a separate thread with its own runtime, avoiding the “cannot start a runtime from within a runtime” panic.
Sourcepub fn tell_blocking<M>(&self, msg: M, timeout: Option<Duration>) -> Result<()>
👎Deprecated since 0.10.0: Use blocking_tell instead. Timeout parameter is ignored.
pub fn tell_blocking<M>(&self, msg: M, timeout: Option<Duration>) -> Result<()>
blocking_tell instead. Timeout parameter is ignored.Synchronous version of ActorRef::tell that blocks until the message is sent.
This method is intended for use within tokio::task::spawn_blocking contexts.
Deprecated: Use blocking_tell instead. The timeout parameter is ignored.
Sourcepub fn ask_blocking<M>(
&self,
msg: M,
timeout: Option<Duration>,
) -> Result<T::Reply>
👎Deprecated since 0.10.0: Use blocking_ask instead. Timeout parameter is ignored.
pub fn ask_blocking<M>( &self, msg: M, timeout: Option<Duration>, ) -> Result<T::Reply>
blocking_ask instead. Timeout parameter is ignored.Synchronous version of ActorRef::ask that blocks until the reply is received.
This method is intended for use within tokio::task::spawn_blocking contexts.
Deprecated: Use blocking_ask instead. The timeout parameter is ignored.
Sourcepub async fn ask_join<M, R>(&self, msg: M) -> Result<R>
pub async fn ask_join<M, R>(&self, msg: M) -> Result<R>
Sends a message to an actor expecting a JoinHandle reply and awaits its completion.
This method is specifically designed for the pattern where message handlers spawn
long-running asynchronous tasks using tokio::spawn and return the JoinHandle.
Instead of manually handling the JoinHandle, this method automatically awaits
the spawned task and returns the final result.
§Common Pattern
This method supports the following actor pattern:
use rsactor::{Actor, ActorRef, message_handlers};
use tokio::task::JoinHandle;
use std::time::Duration;
#[derive(Actor)]
struct WorkerActor;
struct HeavyTask {
data: String,
}
#[message_handlers]
impl WorkerActor {
#[handler]
async fn handle_heavy_task(
&mut self,
msg: HeavyTask,
_: &ActorRef<Self>
) -> JoinHandle<String> {
let data = msg.data.clone();
// Spawn a long-running task to avoid blocking the actor
tokio::spawn(async move {
tokio::time::sleep(Duration::from_secs(5)).await;
format!("Processed: {}", data)
})
}
}§Usage Examples
See the examples/ask_join_demo.rs file for a complete working example that demonstrates:
- Handlers that return
JoinHandle<T>from spawned tasks - Using
ask_joinvs regularaskwith manual await - Error handling for panicked and cancelled tasks
- Concurrent task execution patterns
§Error Handling
This method can return errors in several scenarios:
- Communication errors (actor not available, channels closed):
Error::Send,Error::Receive - Task execution errors (task panicked, cancelled):
Error::Join - Type casting errors:
Error::Downcast
The Error::Join variant includes the original tokio::task::JoinError
which provides detailed information about task failures, such as whether
the task was cancelled or panicked.
§Type Safety
This method enforces compile-time type safety:
- The message type
Mmust be handled by actorT - The handler must return
tokio::task::JoinHandle<R> - The final return type
Ris automatically inferred and type-checked