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 and is already being used in production products under active development. While core APIs are stable, some features may be refined in future releases.
Core Features
Actor System
- Minimalist Design: Focuses on core actor model primitives with a clean API
- Tokio-Native: Built for the
tokioasynchronous runtime - Actor Derive Macro:
#[derive(Actor)]for simple actors that don't need complex initialization
Message Passing
| Method | Description |
|---|---|
ask / ask_with_timeout |
Send a message and asynchronously await a reply |
tell / tell_with_timeout |
Send a message without waiting for a reply (fire-and-forget) |
blocking_ask / blocking_tell |
Blocking versions for tokio::task::spawn_blocking contexts (aliases: ask_blocking / tell_blocking) |
- Macro-Assisted Handlers:
#[message_handlers]attribute macro with#[handler]method attributes for automatic message handling
Actor Lifecycle
Three well-defined hooks for managing actor behavior:
on_start: Initializes the actor's state (required)on_run: Runs concurrently with message processing, returnsboolto control repeated invocation (optional)on_stop: Cleanup before termination, withkilledflag for graceful vs immediate (optional)
Supports graceful termination (stop()) and immediate termination (kill()), with ActorResult enum representing lifecycle outcomes.
Type Safety
- Compile-Time Safety:
ActorRef<T>ensures message handling consistency and prevents type-related runtime errors - Handler Traits:
TellHandler<M>andAskHandler<M, R>enable unified management of different actor types in a single collection - Actor Control Traits:
ActorControlandWeakActorControlprovide type-erased lifecycle management - Only
SendRequired: Actor structs only needSendtrait (notSync), enabling interior mutability types likestd::cell::Cell
Observability
- Optional Tracing: Built-in support via
tracingfeature flag for actor lifecycle events, message handling, and performance metrics - Metrics Support: Optional
metricsfeature for monitoring message counts, processing times, and actor uptime
Why rsActor?
Focused Scope
Unlike broader frameworks like Actix, rsActor specializes exclusively in local, in-process actor systems. This focused approach eliminates complexity from unused features like remote actors or clustering, resulting in a cleaner API and smaller footprint.
Key Advantages
- Simplicity First: Minimal API surface with sensible defaults
- Type-Safe by Default:
ActorRef<T>ensures compile-time message validation with zero runtime overhead - Flexible Type Erasure: Handler traits enable managing heterogeneous actor collections without sacrificing type safety
- Production-Ready Observability: Integrated tracing and metrics support
- Mutex-Free Design: No shared locks between actors - state is isolated within each actor
Getting Started
1. Add Dependency
[]
= "0.14" # Check crates.io for the latest version
# Optional: Enable tracing support for detailed observability
# rsactor = { version = "0.14", 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 the recommended approach 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 concepts with
#[message_handlers]macro - actor_with_timeout - Using timeouts for actor communication
- actor_async_worker - Inter-actor communication with async tasks
- actor_blocking_task - Using blocking APIs with actors
- dining_philosophers - Classic concurrency problem implementation
- weak_reference_demo - Working with weak actor references and lifecycle
- handler_demo - Using handler traits for unified actor management
- ask_join_demo - Using
ask_joinfor CPU/IO-bound operations - metrics_demo - Actor performance monitoring (requires
metricsfeature) - tracing_demo - Structured logging and actor lifecycle tracing
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.14", = ["tracing"] }
= "0.1"
= "0.3"
All examples include tracing support. Here's the recommended initialization pattern:
async
Run any example with tracing enabled:
RUST_LOG=debug
Deadlock Detection
rsActor includes built-in runtime deadlock detection for ask cycles. When enabled, the framework maintains a wait-for graph and detects circular dependencies before they cause a deadlock.
Actor A handler: actor_ref_b.ask(msg).await ← waiting for B's reply
Actor B handler: actor_ref_a.ask(msg).await ← waiting for A's reply
→ Deadlock detected! Panic with cycle path: A(#1) -> B(#2) -> A(#1)
Activation: Enabled automatically with the deadlock-detection feature flag:
[]
= { = "0.14", = ["deadlock-detection"] }
Detected scenarios include self-ask, 2-actor cycles (A → B → A), and indirect chains (A → B → C → A). When a cycle is found, the framework panics with a descriptive message showing the full cycle path, because deadlocks are design errors that should be fixed during development.
For more details, see the Deadlock Detection Guide.
Handler Traits
Handler traits (TellHandler, AskHandler, WeakTellHandler, WeakAskHandler) enable unified management of different actor types handling the same message in a single collection. See the Handler Traits Documentation for details.
Actor Control Traits
Actor control traits (ActorControl, WeakActorControl) provide type-erased lifecycle management for different actor types in a single collection. Handler traits provide as_control() and as_weak_control() methods to access lifecycle operations.
Documentation
- Getting Started - Quick start guide
- Actor Model - Actor model concepts
- Architecture - System architecture overview
- Best Practices - Recommended patterns and practices
- Debugging Guide - Error handling, dead letter tracking, and troubleshooting
- Deadlock Detection - Runtime deadlock detection for
askcycles - Metrics Guide - Actor performance monitoring
- Tracing Guide - Detailed observability with tracing
- FAQ - Common questions and answers
Contributing
We welcome contributions! Here's how to get started:
Development Setup
# Run tests
# Run examples
# With tracing
RUST_LOG=debug
Code Quality
Before submitting a PR, ensure:
Ways to Contribute
- Bug reports and fixes
- Documentation improvements
- New examples
- Performance optimizations
- Feature requests
Claude Code Skills
rsActor provides Claude Code skills to help AI assistants write correct rsactor code.
Installation
# Global installation (recommended)
|
# Project-local installation
|
Available Skills
- rsactor-actor: Create new actors with proper patterns
- rsactor-handler: Add message handlers to existing actors
- rsactor-guide: API reference and troubleshooting guide
License
This project is licensed under the Apache License 2.0. See the LICENSE-APACHE file for details.