{"id":34614166,"url":"https://github.com/mikai233/actor-rs","last_synced_at":"2026-03-15T11:02:46.617Z","repository":{"id":204252248,"uuid":"711190128","full_name":"mikai233/actor-rs","owner":"mikai233","description":"A minimal Rust implementation of the Akka actor model.","archived":false,"fork":false,"pushed_at":"2026-03-06T15:54:25.000Z","size":1969,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-03-06T19:27:31.916Z","etag":null,"topics":["actor","akka","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mikai233.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2023-10-28T13:36:37.000Z","updated_at":"2026-03-06T15:54:29.000Z","dependencies_parsed_at":"2023-12-21T07:53:17.186Z","dependency_job_id":null,"html_url":"https://github.com/mikai233/actor-rs","commit_stats":null,"previous_names":["mikai233/actor-rs"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mikai233/actor-rs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikai233%2Factor-rs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikai233%2Factor-rs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikai233%2Factor-rs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikai233%2Factor-rs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mikai233","download_url":"https://codeload.github.com/mikai233/actor-rs/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikai233%2Factor-rs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30540736,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-15T07:17:37.589Z","status":"ssl_error","status_checked_at":"2026-03-15T07:17:31.738Z","response_time":61,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: 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","akka","rust"],"created_at":"2025-12-24T14:20:02.791Z","updated_at":"2026-03-15T11:02:46.612Z","avatar_url":"https://github.com/mikai233.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# actor-rs\n\n\u003e ### ⚠️ Project Status: On Hold / Blocked\n\u003e\n\u003e This project is currently blocked and will not be updated for the time being. I am dissatisfied with the current code architecture and believe it is unreasonable. A complete redesign is needed, which will involve significant code changes. I currently do not have enough time to dedicate to this major overhaul.\n\nThe goal of this project is to port a minimal functional Scala Actor framework ([akka](https://doc.akka.io/docs/akka/current/typed/guide/introduction.html)) to Rust. Most of the logic refers to Akka's implementation, while some parts adopt different logic to achieve the same functionality due to language differences and my own understanding.\n\nAkka uses the Gossip protocol to maintain cluster state consistency. Currently, this project uses etcd as the configuration center for the entire cluster instead of Gossip. The Gossip protocol will be implemented in the future.\n\n# Core Planned Features\n\n- [x] actor\n- [x] router\n- [ ] cluster router\n- [x] remote\n- [x] cluster (unstable)\n- [x] cluster-sharding\n- [x] cluster singleton\n- [ ] distributed pubsub\n- [x] circuit breaker\n\n# Usage\n\n## Declaring an Actor\n\n```rust\nuse actor_core::Actor;\n\nstruct MyActor;\n\nimpl Actor for MyActor {}\n```\n\n## Handling Actor Messages\n\n```rust\n#[derive(Debug, EmptyCodec)]\nstruct MyMessage {\n    name: String,\n}\n\n#[async_trait]\nimpl Message for MyMessage {\n    type A = MyActor;\n\n    async fn handle(self: Box\u003cSelf\u003e, _context: \u0026mut ActorContext, _actor: \u0026mut Self::A) -\u003e anyhow::Result\u003c()\u003e {\n        println!(\"{:?}\", self.name);\n        Ok(())\n    }\n}\n```\n\n## Creating an Actor\n\n```rust\n#[tokio::main]\nasync fn main() -\u003e anyhow::Result\u003c()\u003e {\n    let system = ActorSystem::create(\"mikai233\", ActorSetting::default())?;\n    let my_actor = system.spawn(Props::create(|_| Ok(MyActor)), \"my_actor\")?;\n    system.await?;\n    Ok(())\n}\n```\n\n## Sending Messages to an Actor\n\n```rust\nmy_actor.tell(DynMessage::user(MyMessage { name: \"hello\".to_string() }), ActorRef::no_sender());\n```\n\n## Core Traits\n\n### Actor\n\n```rust\n#[async_trait]\npub trait Actor: Send + Any {\n    #[allow(unused_variables)]\n    async fn started(\u0026mut self, context: \u0026mut ActorContext) -\u003e anyhow::Result\u003c()\u003e {\n        Ok(())\n    }\n\n    #[allow(unused_variables)]\n    async fn stopped(\u0026mut self, context: \u0026mut ActorContext) -\u003e anyhow::Result\u003c()\u003e {\n        Ok(())\n    }\n\n    #[allow(unused_variables)]\n    fn on_child_failure(\u0026mut self, context: \u0026mut ActorContext, child: \u0026ActorRef, error: \u0026anyhow::Error) -\u003e Directive {\n        Directive::Resume\n    }\n\n    #[allow(unused_variables)]\n    async fn on_recv(\u0026mut self, context: \u0026mut ActorContext, message: DynMessage) -\u003e anyhow::Result\u003cOption\u003cDynMessage\u003e\u003e {\n        Ok(Some(message))\n    }\n}\n```\n\nTo start an actor, you need to define a struct that implements this `trait`.\n\n### Message\n\n```rust\npub trait CodecMessage: Any + Send {\n    fn into_any(self: Box\u003cSelf\u003e) -\u003e Box\u003cdyn Any\u003e;\n\n    fn as_any(\u0026self) -\u003e \u0026dyn Any;\n\n    fn into_codec(self: Box\u003cSelf\u003e) -\u003e Box\u003cdyn CodecMessage\u003e;\n\n    fn decoder() -\u003e Option\u003cBox\u003cdyn MessageDecoder\u003e\u003e where Self: Sized;\n\n    fn encode(self: Box\u003cSelf\u003e, reg: \u0026MessageRegistry) -\u003e anyhow::Result\u003cVec\u003cu8\u003e\u003e;\n\n    fn clone_box(\u0026self) -\u003e anyhow::Result\u003cBox\u003cdyn CodecMessage\u003e\u003e;\n\n    fn cloneable(\u0026self) -\u003e bool;\n\n    fn into_dyn(self) -\u003e DynMessage;\n}\n```\n\nThe top-level `trait` that actor messages need to implement. It determines whether the message needs serialization (if a message is only handled locally, serialization is not required) and whether it can be cloned.\n\n```rust\n#[async_trait]\npub trait Message: CodecMessage {\n    type A: Actor;\n\n    async fn handle(self: Box\u003cSelf\u003e, context: \u0026mut ActorContext, actor: \u0026mut Self::A) -\u003e anyhow::Result\u003c()\u003e;\n}\n```\n\nMessages sent to an actor must implement the `Message` trait in addition to the `CodecMessage` trait. This trait determines the handling logic of the message within the actor.\n\n```rust\npub trait OrphanMessage: CodecMessage {}\n```\n\nIn addition to fire-and-forget (tell), communication between actors also supports the request-response (ask) pattern. In this case, the returned message needs to implement the `OrphanMessage` trait. This trait serves only as a marker to ensure the user correctly uses the framework's interface. The `CodecMessage` trait provides procedural macros to quickly implement this trait and reduce boilerplate code (see below).\n\n## Serialization and DynMessage\n\n`DynMessage` represents an actor message. After receiving this message, the actor will downcast `DynMessage` to a specific message type based on its own type and then call the `handle` method. If the downcast fails, it means the message does not belong to this actor.\n\nWhen declaring an actor message, you need to derive a macro attribute to determine whether the message supports serialization and cloning. For example, `EmptyCodec` indicates that the message does not need serialization and cannot be cloned (can only be sent to local actors). `CEmptyCodec` indicates no serialization but supports cloning (requires the `Clone` macro). `MessageCodec` indicates that serialization is required; when sent to a remote actor, the message will be serialized and deserialized. This procedural macro uses `bincode` by default, so you need to add `bincode::Serialize` and `bincode::Deserialize`. For other custom serialization needs, you can implement the `CodecMessage` trait yourself.\n\n```rust\npub trait CodecMessage: Any + Send {\n    fn into_any(self: Box\u003cSelf\u003e) -\u003e Box\u003cdyn Any\u003e;\n\n    fn as_any(\u0026self) -\u003e \u0026dyn Any;\n\n    fn decoder() -\u003e Option\u003cBox\u003cdyn MessageDecoder\u003e\u003e where Self: Sized;\n\n    fn encode(\u0026self, reg: \u0026MessageRegistry) -\u003e Result\u003cVec\u003cu8\u003e, EncodeError\u003e;\n\n    fn dyn_clone(\u0026self) -\u003e Option\u003cDynMessage\u003e;\n\n    fn is_cloneable(\u0026self) -\u003e bool;\n}\n```\n\nSimilarly, there are different types like `SystemCodec`, `CSystemCodec`, `OrphanCodec`, etc. Those starting with `system` are actor system messages (generally not used in business logic). Those starting with `orphan` are messages returned by `ask` (response) that need to be derived.\n\n# Cluster Sharding\n\nThis module is a core feature of this project. Through Cluster Sharding, a large-scale cluster system can be achieved. Actors on each node can be accessed through a unique ID without worrying about which node the actor is on. It also enables dynamic expansion and contraction. The implementation logic refers to Akka.\n\n## Usage\n\nFor sharding examples, please refer to [sharding.rs](actor-playgroud/src/sharding.rs).\n\nThe general usage flow is:\n\n1. When building `ActorSetting`, register all internal messages required for cluster sharding in the `MessageRegistry`.\n2. Register the `ClusterSharding` extension module in the `ActorSystem`.\n3. Define the message router `MessageExtractor`. Each message will call the `entity_id` method of `MessageExtractor`. Messages are routed based on the returned ID. `shard_id` is used to determine which Shard this Actor belongs to.\n4. Start a `ShardRegion` via the `start` method of `ClusterSharding`. `ShardRegion` is a special Actor that manages a group of `Shard`s. A `Shard` is a group of Actors with the same `shard_id`.\n\nThen, by sending messages to `ShardRegion`, it routes messages according to the `entity_id` method of `MessageExtractor`. If the `Shard` corresponding to the `entity_id` does not exist, a new `Shard` will be created, followed by a new Actor to handle the message.\n\n# More examples can be found in [actor-playground](actor-playgroud/src)\n\n## Future Plans\n\n- [ ] Improve test cases\n- [ ] Improve documentation\n- [ ] Clean up TODOs\n- [ ] Optimize implementation logic\n\n## Acknowledgments\n\nSpecial thanks to [JetBrains](https://www.jetbrains.com/?from=actor-rs) for providing free IDE licenses for open-source projects.\n\n![JetBrains logo](https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.png)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmikai233%2Factor-rs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmikai233%2Factor-rs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmikai233%2Factor-rs/lists"}