{"id":28931427,"url":"https://github.com/hiking90/rsactor","last_synced_at":"2026-02-14T08:11:46.421Z","repository":{"id":292962527,"uuid":"949280066","full_name":"hiking90/rsactor","owner":"hiking90","description":"A Simple and Efficient In-Process Actor Model Implementation for Rust.","archived":false,"fork":false,"pushed_at":"2026-02-01T02:26:32.000Z","size":3386,"stargazers_count":13,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-01T12:20:15.059Z","etag":null,"topics":["actor","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hiking90.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-03-16T04:41:53.000Z","updated_at":"2026-02-01T02:26:29.000Z","dependencies_parsed_at":"2025-06-04T13:41:34.561Z","dependency_job_id":"38c70915-c1b7-41c8-8433-beda86aecf07","html_url":"https://github.com/hiking90/rsactor","commit_stats":null,"previous_names":["hiking90/rsactor"],"tags_count":19,"template":false,"template_full_name":null,"purl":"pkg:github/hiking90/rsactor","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hiking90%2Frsactor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hiking90%2Frsactor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hiking90%2Frsactor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hiking90%2Frsactor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hiking90","download_url":"https://codeload.github.com/hiking90/rsactor/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hiking90%2Frsactor/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29439827,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-14T07:24:13.446Z","status":"ssl_error","status_checked_at":"2026-02-14T07:23:58.969Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["actor","rust"],"created_at":"2025-06-22T16:02:35.950Z","updated_at":"2026-02-14T08:11:46.407Z","avatar_url":"https://github.com/hiking90.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rsActor\n[![CI](https://github.com/hiking90/rsactor/actions/workflows/rust.yml/badge.svg)](https://github.com/hiking90/rsactor/actions/workflows/rust.yml)\n[![Crates.io](https://img.shields.io/crates/v/rsactor.svg)](https://crates.io/crates/rsactor)\n[![Docs.rs](https://docs.rs/rsactor/badge.svg)](https://docs.rs/rsactor)\n[![Rust Version](https://img.shields.io/badge/rustc-1.75+-blue.svg)](https://blog.rust-lang.org/)\n\nA Simple and Efficient In-Process Actor Model Implementation for Rust.\n\n`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.\n\n**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.\n\n## Core Features\n\n### Actor System\n- **Minimalist Design**: Focuses on core actor model primitives with a clean API\n- **Tokio-Native**: Built for the `tokio` asynchronous runtime\n- **Actor Derive Macro**: `#[derive(Actor)]` for simple actors that don't need complex initialization\n\n### Message Passing\n| Method                           | Description                                                  |\n| -------------------------------- | ------------------------------------------------------------ |\n| `ask` / `ask_with_timeout`       | Send a message and asynchronously await a reply              |\n| `tell` / `tell_with_timeout`     | Send a message without waiting for a reply (fire-and-forget) |\n| `blocking_ask` / `blocking_tell` | Blocking versions for `tokio::task::spawn_blocking` contexts (aliases: `ask_blocking` / `tell_blocking`) |\n\n- **Macro-Assisted Handlers**: `#[message_handlers]` attribute macro with `#[handler]` method attributes for automatic message handling\n\n### Actor Lifecycle\nThree well-defined hooks for managing actor behavior:\n- `on_start`: Initializes the actor's state (required)\n- `on_run`: Runs concurrently with message processing, returns `bool` to control repeated invocation (optional)\n- `on_stop`: Cleanup before termination, with `killed` flag for graceful vs immediate (optional)\n\nSupports **graceful termination** (`stop()`) and **immediate termination** (`kill()`), with `ActorResult` enum representing lifecycle outcomes.\n\n### Type Safety\n- **Compile-Time Safety**: `ActorRef\u003cT\u003e` ensures message handling consistency and prevents type-related runtime errors\n- **Handler Traits**: `TellHandler\u003cM\u003e` and `AskHandler\u003cM, R\u003e` enable unified management of different actor types in a single collection\n- **Actor Control Traits**: `ActorControl` and `WeakActorControl` provide type-erased lifecycle management\n- **Only `Send` Required**: Actor structs only need `Send` trait (not `Sync`), enabling interior mutability types like `std::cell::Cell`\n\n### Observability\n- **Optional Tracing**: Built-in support via `tracing` feature flag for actor lifecycle events, message handling, and performance metrics\n- **Metrics Support**: Optional `metrics` feature for monitoring message counts, processing times, and actor uptime\n\n## Why rsActor?\n\n### Focused Scope\nUnlike 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.\n\n### Key Advantages\n\n- **Simplicity First**: Minimal API surface with sensible defaults\n- **Type-Safe by Default**: `ActorRef\u003cT\u003e` ensures compile-time message validation with zero runtime overhead\n- **Flexible Type Erasure**: Handler traits enable managing heterogeneous actor collections without sacrificing type safety\n- **Production-Ready Observability**: Integrated tracing and metrics support\n- **Mutex-Free Design**: No shared locks between actors - state is isolated within each actor\n\n## Getting Started\n\n### 1. Add Dependency\n\n```toml\n[dependencies]\nrsactor = \"0.13\" # Check crates.io for the latest version\n\n# Optional: Enable tracing support for detailed observability\n# rsactor = { version = \"0.13\", features = [\"tracing\"] }\n```\n\nFor using the derive macros, you'll also need the `message_handlers` attribute macro which is included by default.\n\n### 2. Message Handling with `#[message_handlers]`\n\nrsActor 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:\n\n- **Selective Processing**: Only methods marked with `#[handler]` are treated as message handlers.\n- **Clean Separation**: Regular methods can coexist with message handlers within the same `impl` block.\n- **Automatic Generation**: The macro automatically generates the necessary `Message` trait implementations and handler registrations.\n- **Type Safety**: Message handler signatures are verified at compile time.\n- **Reduced Boilerplate**: Eliminates the need to manually implement `Message` traits.\n\n### 3. Choose Your Actor Creation Approach\n\n#### Option A: Simple Actor with `#[derive(Actor)]`\n\nFor simple actors that don't need complex initialization logic, use the `#[derive(Actor)]` macro:\n\n```rust\nuse rsactor::{Actor, ActorRef, message_handlers, spawn};\n\n// 1. Define message types\nstruct Increment;\nstruct GetCount;\n\n// 2. Define your actor struct and derive Actor\n#[derive(Actor)]\nstruct CounterActor {\n    count: u32,\n}\n\n// 3. Use the #[message_handlers] macro with #[handler] attributes to automatically generate Message trait implementations\n#[message_handlers]\nimpl CounterActor {\n    #[handler]\n    async fn handle_increment(\u0026mut self, _msg: Increment, _: \u0026ActorRef\u003cSelf\u003e) {\n        self.count += 1;\n    }\n\n    #[handler]\n    async fn handle_get_count(\u0026mut self, _msg: GetCount, _: \u0026ActorRef\u003cSelf\u003e) -\u003e u32 {\n        self.count\n    }\n}\n\n// 4. Usage\n#[tokio::main]\nasync fn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    let actor = CounterActor { count: 0 };\n    let (actor_ref, _join_handle) = spawn::\u003cCounterActor\u003e(actor);\n\n    actor_ref.tell(Increment).await?;\n    let count = actor_ref.ask(GetCount).await?;\n    println!(\"Count: {}\", count); // Prints: Count: 1\n\n    actor_ref.stop().await?;\n    Ok(())\n}\n```\n\n#### Option B: Custom Actor Implementation with Manual Initialization\n\nFor actors that need custom initialization logic, implement the `Actor` trait manually:\n\n```rust\nuse rsactor::{Actor, ActorRef, message_handlers, spawn};\nuse anyhow::Result;\nuse tracing::info;\n\n// Define actor struct\n#[derive(Debug)] // Added Debug for printing the actor in ActorResult\nstruct CounterActor {\n    count: u32,\n}\n\n// Implement Actor trait\nimpl Actor for CounterActor {\n    type Args = u32; // Define an args type for actor creation\n    type Error = anyhow::Error;\n\n    // on_start is required and must be implemented.\n    // on_run and on_stop are optional and have default implementations.\n    async fn on_start(initial_count: Self::Args, actor_ref: \u0026ActorRef\u003cSelf\u003e) -\u003e Result\u003cSelf, Self::Error\u003e {\n        info!(\"CounterActor (id: {}) started. Initial count: {}\", actor_ref.identity(), initial_count);\n        Ok(CounterActor {\n            count: initial_count,\n        })\n    }\n}\n\n// Define message types\nstruct Increment(u32);\n\n// Use message_handlers macro for message handling\n#[message_handlers]\nimpl CounterActor {\n    #[handler]\n    async fn handle_increment(\u0026mut self, msg: Increment, _actor_ref: \u0026ActorRef\u003cSelf\u003e) -\u003e u32 {\n        self.count += msg.0;\n        self.count\n    }\n}\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c()\u003e {\n    tracing_subscriber::fmt().init(); // Initialize tracing\n\n    info!(\"Creating CounterActor\");\n\n    let (actor_ref, join_handle) = spawn::\u003cCounterActor\u003e(0u32); // Pass initial count as Args\n    info!(\"CounterActor spawned with ID: {}\", actor_ref.identity());\n\n    let new_count: u32 = actor_ref.ask(Increment(5)).await?;\n    info!(\"Incremented count: {}\", new_count);\n\n    actor_ref.stop().await?;\n    info!(\"Stop signal sent to CounterActor (ID: {})\", actor_ref.identity());\n\n    let actor_result = join_handle.await?;\n    info!(\n        \"CounterActor (ID: {}) task completed. Result: {:?}\",\n        actor_ref.identity(),\n        actor_result\n    );\n\n    Ok(())\n}\n```\n\n## Examples\n\nrsActor comes with several examples that demonstrate various features and use cases:\n\n* **[basic](./examples/basic.rs)** - Simple counter actor demonstrating core concepts with `#[message_handlers]` macro\n* **[actor_with_timeout](./examples/actor_with_timeout.rs)** - Using timeouts for actor communication\n* **[actor_async_worker](./examples/actor_async_worker.rs)** - Inter-actor communication with async tasks\n* **[actor_blocking_task](./examples/actor_blocking_task.rs)** - Using blocking APIs with actors\n* **[dining_philosophers](./examples/dining_philosophers.rs)** - Classic concurrency problem implementation\n* **[weak_reference_demo](./examples/weak_reference_demo.rs)** - Working with weak actor references and lifecycle\n* **[handler_demo](./examples/handler_demo.rs)** - Using handler traits for unified actor management\n* **[ask_join_demo](./examples/ask_join_demo.rs)** - Using `ask_join` for CPU/IO-bound operations\n* **[metrics_demo](./examples/metrics_demo.rs)** - Actor performance monitoring (requires `metrics` feature)\n* **[tracing_demo](./examples/tracing_demo.rs)** - Structured logging and actor lifecycle tracing\n\nRun any example with:\n```bash\ncargo run --example \u003cexample_name\u003e\n```\n\nAll examples support tracing when enabled with the `tracing` feature:\n```bash\nRUST_LOG=debug cargo run --example \u003cexample_name\u003e --features tracing\n```\n\n## Optional Features\n\n### Tracing Support\n\nrsActor provides optional tracing support for comprehensive observability into actor behavior. When enabled, the framework emits structured trace events for:\n\n- Actor lifecycle events (start, stop, termination scenarios)\n- Message sending and handling with timing information\n- Reply processing and error handling\n- Performance metrics (message processing duration)\n\nTo enable tracing support, add the `tracing` feature to your dependencies:\n\n```toml\n[dependencies]\nrsactor = { version = \"0.13\", features = [\"tracing\"] }\ntracing = \"0.1\"\ntracing-subscriber = \"0.3\"\n```\n\nAll examples include tracing support. Here's the recommended initialization pattern:\n\n```rust\n#[tokio::main]\nasync fn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    // Initialize tracing subscriber\n    tracing_subscriber::fmt()\n        .with_max_level(tracing::Level::DEBUG)\n        .with_target(false)\n        .init();\n\n    // Your actor code here...\n    Ok(())\n}\n```\n\nRun any example with tracing enabled:\n```bash\nRUST_LOG=debug cargo run --example basic --features tracing\n```\n\n## Handler Traits\n\nHandler 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](./docs/handler_traits_design.md) for details.\n\n## Actor Control Traits\n\nActor 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.\n\n## Documentation\n\n- **[Getting Started](./docs/getting_started.md)** - Quick start guide\n- **[Actor Model](./docs/actor_model.md)** - Actor model concepts\n- **[Architecture](./docs/Architecture.md)** - System architecture overview\n- **[Best Practices](./docs/best_practices.md)** - Recommended patterns and practices\n- **[Debugging Guide](./docs/debugging_guide.md)** - Error handling, dead letter tracking, and troubleshooting\n- **[Metrics Guide](./docs/metrics.md)** - Actor performance monitoring\n- **[Tracing Guide](./docs/tracing.md)** - Detailed observability with tracing\n- **[FAQ](./docs/FAQ.md)** - Common questions and answers\n\n## Contributing\n\nWe welcome contributions! Here's how to get started:\n\n### Development Setup\n\n```bash\ngit clone https://github.com/hiking90/rsactor.git\ncd rsactor\n\n# Run tests\ncargo test --all-features\n\n# Run examples\ncargo run --example basic\n\n# With tracing\nRUST_LOG=debug cargo run --example basic --features tracing\n```\n\n### Code Quality\n\nBefore submitting a PR, ensure:\n\n```bash\ncargo fmt                                                    # Format code\ncargo clippy --all-targets --all-features -- -D warnings    # Lint check\ncargo test --all-features                                    # All tests pass\n```\n\n### Ways to Contribute\n\n- Bug reports and fixes\n- Documentation improvements\n- New examples\n- Performance optimizations\n- Feature requests\n\n## Claude Code Skills\n\nrsActor provides [Claude Code](https://claude.ai/code) skills to help AI assistants write correct rsactor code.\n\n### Installation\n\n```bash\n# Global installation (recommended)\ncurl -sSL https://raw.githubusercontent.com/hiking90/rsactor/main/install-skills.sh | bash\n\n# Project-local installation\ncurl -sSL https://raw.githubusercontent.com/hiking90/rsactor/main/install-skills.sh | bash -s -- --local\n```\n\n### Available Skills\n\n- **rsactor-actor**: Create new actors with proper patterns\n- **rsactor-handler**: Add message handlers to existing actors\n- **rsactor-guide**: API reference and troubleshooting guide\n\n## License\n\nThis project is licensed under the Apache License 2.0. See the [LICENSE-APACHE](LICENSE-APACHE) file for details.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhiking90%2Frsactor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhiking90%2Frsactor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhiking90%2Frsactor/lists"}