rsActor
A Simple and Efficient In-Process Actor Model Implementation for Rust.
rsActor is a lightweight, Tokio-based actor framework in Rust focused on providing a simple and efficient actor model for local, in-process systems. It emphasizes clean message-passing semantics and straightforward actor lifecycle management while maintaining high performance for Rust applications.
Note: This project is actively evolving. While core APIs are stable, some features may be refined in future releases.
Core Features
- Minimalist Actor System: Focuses on core actor model primitives.
- Actor Derive Macro:
#[derive(Actor)]for simple actors that don't need complex initialization. - Message Passing:
ask/ask_with_timeout: Send a message and asynchronously await a reply.tell/tell_with_timeout: Send a message without waiting for a reply.ask_blocking/tell_blocking: Blocking versions fortokio::task::spawn_blockingcontexts.
- Straightforward Actor Lifecycle: Provides
on_start,on_run, andon_stophooks for managing actor behavior:on_start:async fn on_start(args: Self::Args, actor_ref: &ActorRef<Self>) -> Result<Self, Self::Error>- Initializes the actor's state. This method is required.on_run:async fn on_run(&mut self, actor_ref: &ActorWeak<Self>) -> Result<(), Self::Error>- Contains the actor's main execution logic, which runs concurrently with message handling. This method is optional and has a default implementation.on_stop:async fn on_stop(&mut self, actor_ref: &ActorWeak<Self>, killed: bool) -> Result<(), Self::Error>- Performs cleanup before the actor terminates. Thekilledflag indicates whether the termination was graceful (false) or immediate (true). This method is optional and has a default implementation.
- Graceful & Immediate Termination: Actors can be stopped gracefully or killed.
ActorResult: Enum representing the outcome of an actor's lifecycle (e.g., completed, failed).- Macro-Assisted Message Handling:
#[message_handlers]attribute macro with#[handler]method attributes for automatic message handling
- Tokio-Native: Built for the
tokioasynchronous runtime. - Strong Type Safety: Provides compile-time (
ActorRef<T>) type safety, ensuring message handling consistency and preventing type-related runtime errors. - Only
SendTrait Required: Actor structs only need to implement theSendtrait (notSync), enabling the use of interior mutability types likestd::cell::Cellfor internal state management without synchronization overhead. TheActortrait andMessageHandlertrait (via#[message_handlers]macro) are also required, but they don't add any additional constraints on the actor's fields. - Optional Tracing Support: Built-in support for detailed observability using the
tracingcrate. When enabled via thetracingfeature flag, provides comprehensive logging of actor lifecycle events, message handling, and performance metrics.
Getting Started
1. Add Dependency
[]
= "0.9" # Check crates.io for the latest version
# Optional: Enable tracing support for detailed observability
# rsactor = { version = "0.9", features = ["tracing"] }
For using the derive macros, you'll also need the message_handlers attribute macro which is included by default.
2. Message Handling with #[message_handlers]
rsActor uses the #[message_handlers] attribute macro combined with #[handler] method attributes for message handling. This is required for all actors and offers several advantages:
- Selective Processing: Only methods marked with
#[handler]are treated as message handlers. - Clean Separation: Regular methods can coexist with message handlers within the same
implblock. - Automatic Generation: The macro automatically generates the necessary
Messagetrait implementations and handler registrations. - Type Safety: Message handler signatures are verified at compile time.
- Reduced Boilerplate: Eliminates the need to manually implement
Messagetraits.
3. Choose Your Actor Creation Approach
Option A: Simple Actor with #[derive(Actor)]
For simple actors that don't need complex initialization logic, use the #[derive(Actor)] macro:
use ;
// 1. Define message types
;
;
// 2. Define your actor struct and derive Actor
// 3. Use the #[message_handlers] macro with #[handler] attributes to automatically generate Message trait implementations
// 4. Usage
async
Option B: Custom Actor Implementation with Manual Initialization
For actors that need custom initialization logic, implement the Actor trait manually:
use ;
use Result;
use info;
// Define actor struct
// Added Debug for printing the actor in ActorResult
// Implement Actor trait
// Define message types
;
// Use message_handlers macro for message handling
async
Examples
rsActor comes with several examples that demonstrate various features and use cases:
- basic - Simple counter actor demonstrating core actor model concepts with
#[message_handlers]macro - derive_macro_demo - Simple example using
#[message_handlers]with#[handler]attributes - message_macro_demo - Demonstrates various message types with the new macro system
- unified_macro_demo - Combined usage of derive and message handler macros
- advanced_derive_demo - Advanced usage patterns with derive macros
- actor_with_timeout - Using timeouts for actor communication
- actor_async_worker - Inter-actor communication with async tasks
- actor_task - Background task communication with actors
- actor_blocking_task - Using blocking APIs with actors
- dining_philosophers - Classic concurrency problem implementation
- weak_reference_demo - Working with weak actor references and lifecycle management
Run any example with:
All examples support tracing when enabled with the tracing feature:
RUST_LOG=debug
Optional Features
Tracing Support
rsActor provides optional tracing support for comprehensive observability into actor behavior. When enabled, the framework emits structured trace events for:
- Actor lifecycle events (start, stop, termination scenarios)
- Message sending and handling with timing information
- Reply processing and error handling
- Performance metrics (message processing duration)
To enable tracing support, add the tracing feature to your dependencies:
[]
= { = "0.9", = ["tracing"] }
= "0.1"
= "0.3"
All examples include tracing support with feature detection. Here's the pattern used:
async
Run any example with tracing enabled:
RUST_LOG=debug
Further Information
For more detailed questions and answers, please see the FAQ.
License
This project is licensed under the Apache License 2.0. See the LICENSE-APACHE file for details.