{"id":13933013,"url":"https://github.com/gamazeps/RobotS","last_synced_at":"2025-07-19T16:32:32.366Z","repository":{"id":73864372,"uuid":"43333844","full_name":"gamazeps/RobotS","owner":"gamazeps","description":"Actor system for Rust","archived":false,"fork":false,"pushed_at":"2017-10-22T13:00:20.000Z","size":5397,"stargazers_count":293,"open_issues_count":2,"forks_count":19,"subscribers_count":25,"default_branch":"master","last_synced_at":"2024-08-08T21:19:51.860Z","etag":null,"topics":["actor-supervision","actors","actorsystem","akka","rust"],"latest_commit_sha":null,"homepage":null,"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/gamazeps.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-MIT","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2015-09-28T23:56:29.000Z","updated_at":"2024-06-27T23:42:32.000Z","dependencies_parsed_at":"2023-09-21T13:32:28.976Z","dependency_job_id":null,"html_url":"https://github.com/gamazeps/RobotS","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gamazeps%2FRobotS","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gamazeps%2FRobotS/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gamazeps%2FRobotS/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gamazeps%2FRobotS/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gamazeps","download_url":"https://codeload.github.com/gamazeps/RobotS/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226643899,"owners_count":17662968,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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-supervision","actors","actorsystem","akka","rust"],"created_at":"2024-08-07T21:01:28.824Z","updated_at":"2024-11-26T23:30:52.676Z","avatar_url":"https://github.com/gamazeps.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"# RobotS\n\n[![Build Status](https://travis-ci.org/gamazeps/RobotS.svg?branch=travis__test)](https://travis-ci.org/gamazeps/RobotS)\n[![Coverage Status](https://coveralls.io/repos/gamazeps/RobotS/badge.svg?branch=master\u0026service=github)](https://coveralls.io/github/gamazeps/RobotS?branch=master)\n\nRobots is a pure rust actor system library, it takes a strong inspiration from [erlang](https://www.erlang.org/) and\n[akka](http://akka.io).\n\nDocumentation can be found [here](http://gamazeps.github.io/RobotS/).\n\n## Maintained status\n\nI am no longer working on this crate, so features will probably not be added by me.\n\nIf you want to add features feel free to submit a PR, I will try to review it within the week.\n\nBugs and errors will nevertheless be corrected if an issue is opened, provided they are not too long\nto correct.\n\n## Build it\n\nThis library can be built on a stable rustc (starting at 1.4.0) version.\n\nA simple\n```bash\ncargo build\n```\nshould be enough.\n\n## Usage\n\n### Initiate the ActorSystem\n\nIn order to use this crate you first need to create an ActorSystem and give it some threads to work\nwith.\n\n```rust\nextern crate robots;\nuse robots::actors::ActorSystem;\n\nfn main() {\n    let actor_system = ActorSystem::new(\"test\".to_owned());\n    actor_system.spawn_threads(1);\n}\n```\n\nYou can also shut down the actor system by calling the `shutdown` method on it, it will  stop all\nthreads and terminate all the actors and their allocated ressources (if you implemented their drop\nproperly).\n\nThat's nice but you need to populate it with some Actors.\n\n### Implement an Actor\n\nIn order to define an actor you need to:\n\n  * Define a struct and have it implement the `Actor` trait.\n  * Have a function with a single argument to create it (a `tuple` will do that if you need multiple\n    values, or `()` if you need none).\n\n```rust\nuse robots::actors::{Actor, ActorCell, ActorContext};\n\nstruct Dummy;\n\nimpl Actor for Dummy {\n    fn receive(\u0026self, _message: Box\u003cAny\u003e, _context: ActorCell) {}\n}\n\nimpl Dummy {\n    fn new(_: ()) -\u003e Dummy {\n        Dummy\n    }\n}\n```\n\n### Instantiate an Actor\n\nNow let's see how to instantiate such an actor.\n\nActors are created with a `Props`, this is a structure containing a constructor for this actor and\nthe argument for it.\n\nThere are two ways to instantiate an actor, it can either be the child of another user created actor\nor be the child of the root actor for user actors.\n\nThe first way looks like:\n\n```rust\nlet props = Props::new(Arc::new(Dummy::new), ());\nlet greeter = context.actor_of(props, \"dummy\".to_owned());\n```\n\nThe second looks like:\n\n```rust\nlet props = Props::new(Arc::new(Dummy::new), ());\nlet _actor = actor_system.actor_of(props, \"dummy\".to_owned());\n```\n\nThe `actor_of` method will give you an `ActorRef` to the created actor.\n\nNote that the first way to create actors is much faster than the second one (about 10 times), so it\nshould only be used if you want to create a new actor hierachy.\n\n### Handle messages\n\nThe actor will receive its messages in the form of `Box\u003cAny\u003e`, this allows the actor to handle\nmultiple types of message which can be usefull in many cases (forwarding messages for example).\n\nIn order to have a concrete type from a `Box\u003cAny\u003e`, you will need to downcast it like in the\nfollowing example.\n\n```rust\nimpl Actor for Printer {\n    fn receive(\u0026self, message: Box\u003cAny\u003e, _context: ActorCell) {\n        if let Ok(message) = Box::\u003cAny\u003e::downcast::\u003cString\u003e(message) {\n            println!(\"{}\", *message);\n        }\n    }\n}\n```\n\nAs you can see this is rather easy.\n\nIf you think that using Box\u0026lt;Any\u003e is very bad and that someone should do terrible things to me, check\n[this post](http://gamazeps.github.io/posts/robots_any.html) before :)\n\n### ActorContext methods\n\nNow let's see how to use the context argument.\n\nThis gives most of the communication methods and features expected of an actor:\n\n```rust\n/// Returns an ActorRef to the Actor.\nfn actor_ref(\u0026self) -\u003e ActorRef;\n\n/// Spawns a child actor.\nfn actor_of(\u0026self, props: Arc\u003cActorFactory\u003e, name: String) -\u003e Result\u003cActorRef, \u0026'static str\u003e;\n\n/// Sends a Message to the targeted ActorRef.\nfn tell\u003cMessageTo: Message\u003e(\u0026self, to: ActorRef, message: MessageTo);\n\n/// Creates a Future, this Future will send the message to the targetted ActorRef (and thus be\n/// the sender of the message).\nfn ask\u003cMessageTo: Message\u003e(\u0026self, to: ActorRef, message: MessageTo, future_name: String) -\u003e ActorRef;\n\n/// Completes a Future.\nfn complete\u003cMessageTo: Message\u003e(\u0026self, to: ActorRef, complete: MessageTo);\n\n/// Tells a future to forward its result to another Actor.\n/// The Future is then dropped.\nfn forward_result\u003cT: Message\u003e(\u0026self, future: ActorRef, to: ActorRef);\n\n/// Tells a future to forward its result to another Future that will be completed with this\n/// result.\n/// The Future is then dropped.\nfn forward_result_to_future\u003cT: Message\u003e(\u0026self, future: ActorRef, to: ActorRef);\n\n/// Sends the Future a closure to apply on its value, the value will be updated with the output\n/// of the closure.\nfn do_computation\u003cT: Message, F: Fn(Box\u003cAny + Send\u003e, ActorCell) -\u003e T + Send + Sync + 'static\u003e\n    (\u0026self, future: ActorRef, closure: F);\n\n/// Requests the targeted actor to stop.\nfn stop(\u0026self, actor_ref: ActorRef);\n\n/// Asks the father of the actor to terminate it.\nfn kill_me(\u0026self);\n\n/// Returns an Arc to the sender of the message being handled.\nfn sender(\u0026self) -\u003e ActorRef;\n\n/// Father of the actor.\nfn father(\u0026self) -\u003e ActorRef;\n\n/// Children of the actor.\nfn children(\u0026self) -\u003e HashMap\u003cArc\u003cActorPath\u003e, ActorRef\u003e;\n\n/// Lifecycle monitoring, list of monitored actors.\nfn monitoring(\u0026self) -\u003e HashMap\u003cArc\u003cActorPath\u003e, (ActorRef, FailureHandler)\u003e;\n\n/// Actors monitoring this actor.\nfn monitored_by(\u0026self) -\u003e Vec\u003cActorRef\u003e;\n\n/// Monitor an actor with the given handler.\nfn monitor(\u0026self, actor: ActorRef, handler: FailureHandler);\n\n/// Logical path to the actor, such as `/user/foo/bar/baz`\nfn path(\u0026self) -\u003e Arc\u003cActorPath\u003e;\n\n/// Future containing an Option\u003cActorRef\u003e with an ActtorRef to the Actor with the given logical\n/// path.\n///\n/// The future will have the path: `$actor/$name_request`\nfn identify_actor(\u0026self, logical_path: String, request_name: String) -\u003e ActorRef;\n\n/// Sends a control message to the given actor.\nfn tell_control(\u0026self, actor: ActorRef, message: ControlMessage);\n\n/// Puts the actor in a state of failure with the given reason.\nfn fail(\u0026self, reason: \u0026'static str);\n```\n\n## Logging\n\nRobotS logs informations on the `info` channel of the `log` crate.\n\nIf you have never used this crate you can simply activate the logs by adding the following lines to\nyour executable:\n\n```rust\nextern crate env_logger;\n\n// Your use and extern crates...\n\nfn main() {\n    env_logger::init().unwrap();\n\n    // Your main code.\n}\n```\n\nYou will need to set the `RUST_LOG` environment variable to `robots=info`. For example when launching the factorial\nexample we see:\n\n```\n➜  RobotS git:(master) ✗ RUST_LOG=robots=info cargo run --example=factorial\n   Compiling RobotS v0.3.0 (file:///home/gamazeps/dev/RobotS)\n     Running `target/debug/examples/factorial`\nINFO:robots::actors::actor_system: Created cthulhu\nINFO:robots::actors::actor_ref: /user receiving a system message\nINFO:robots::actors::actor_system: Created /user actor\nINFO:robots::actors::actor_ref: /system receiving a system message\nINFO:robots::actors::actor_system: Created /system actor\nINFO:robots::actors::actor_system: Launched the first thread\nINFO:robots::actors::actor_system: Created the channel to get an ActorRef from a root actor\nINFO:robots::actors::actor_ref: / is sending a message to /system\nINFO:robots::actors::actor_ref: /system receiving a message\nINFO:robots::actors::actor_ref: /user handling a message\nINFO:robots::actors::actor_ref: /system handling a message\nINFO:robots::actors::actor_ref: /system handling a message\nINFO:robots::actors::actor_cell: creating actor /system/name_resolver\nINFO:robots::actors::actor_ref: /system/name_resolver receiving a system message\nINFO:robots::actors::actor_system: Created the /system/name_resolver actor\nINFO:robots::actors::actor_ref: /system/name_resolver handling a message\nINFO:robots::actors::actor_system: Created the channel to get an ActorRef from a root actor\nINFO:robots::actors::actor_ref: / is sending a message to /user\nINFO:robots::actors::actor_ref: /user receiving a message\nINFO:robots::actors::actor_ref: /user handling a message\nINFO:robots::actors::actor_cell: creating actor /user/sender\nINFO:robots::actors::actor_ref: /user/sender receiving a system message\nINFO:robots::actors::actor_ref: /system/name_resolver receiving a message\nINFO:robots::actors::actor_ref: /user/sender handling a message\nINFO:robots::actors::actor_system: Created the channel to get an ActorRef from a root actor\nINFO:robots::actors::actor_ref: /system/name_resolver handling a message\nINFO:robots::actors::actor_ref: / is sending a message to /user\nINFO:robots::actors::actor_ref: /user receiving a message\n....\n```\n\nThis is a bit verbose but allows you to monitor the proper execution of your program.\n\n## Contributing\n\nAll contribution are welcome, if you have a feature request don't hesitate to open an issue !\n\n## Features\n\n  * Actor communication in a local context.\n  * Actor supervision with an actor hierarchy (each actor supervises its children).\n  * Failure handling with explicit reaosns and handlers.\n  * Ask pattern using Futures for asynchronous requests.\n  * Name resolving (obtaining an ActorRef from a logical path).\n  * Logging.\n\n## TODO\n\n  * Network communication in a transparent manner.\n  * Investigate the performances to shave some microseconds.\n  * Your crazy ideas ?\n\n## Benches\n\nSome crude benchs were written for actor creation and local message passing.\n\nHere are the result on my Intel(R) Core(TM) i5-3317U CPU @ 1.70GHz\n\n```\ntest create_1000_actors                   ... bench:   3,341,549 ns/iter (+/- 173,594)\ntest send_1000_messages                   ... bench:   1,217,572 ns/iter (+/- 196,141)\n```\n\nNevertheless, I have not yet managed to get akka working on my computer so I don't have anything to\nbench against so do what you want with these benches.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgamazeps%2FRobotS","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgamazeps%2FRobotS","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgamazeps%2FRobotS/lists"}