{"id":15010135,"url":"https://github.com/brndnmtthws/genserver","last_synced_at":"2025-04-09T18:04:16.860Z","repository":{"id":56712243,"uuid":"523935802","full_name":"brndnmtthws/genserver","owner":"brndnmtthws","description":"Elixir inspired async actor library for Rust","archived":false,"fork":false,"pushed_at":"2025-01-25T19:42:38.000Z","size":105,"stargazers_count":15,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-23T20:03:05.041Z","etag":null,"topics":["actors","genserver","rust"],"latest_commit_sha":null,"homepage":"https://docs.rs/genserver","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/brndnmtthws.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"github":"brndnmtthws"}},"created_at":"2022-08-12T02:51:07.000Z","updated_at":"2025-03-01T14:21:44.000Z","dependencies_parsed_at":"2024-02-06T05:28:17.131Z","dependency_job_id":"0df12886-1395-4f68-ad88-7f2fa532a6c5","html_url":"https://github.com/brndnmtthws/genserver","commit_stats":{"total_commits":60,"total_committers":3,"mean_commits":20.0,"dds":0.09999999999999998,"last_synced_commit":"fcc49078fa8fedee73c074923b191882a59cae42"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brndnmtthws%2Fgenserver","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brndnmtthws%2Fgenserver/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brndnmtthws%2Fgenserver/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brndnmtthws%2Fgenserver/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/brndnmtthws","download_url":"https://codeload.github.com/brndnmtthws/genserver/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248084171,"owners_count":21045123,"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":["actors","genserver","rust"],"created_at":"2024-09-24T19:30:36.738Z","updated_at":"2025-04-09T18:04:16.817Z","avatar_url":"https://github.com/brndnmtthws.png","language":"Rust","funding_links":["https://github.com/sponsors/brndnmtthws"],"categories":["Rust"],"sub_categories":[],"readme":"[![Docs](https://docs.rs/genserver/badge.svg)](https://docs.rs/genserver) [![Crates.io](https://img.shields.io/crates/v/genserver)](https://crates.io/crates/genserver) [![Build \u0026 test](https://github.com/brndnmtthws/genserver/actions/workflows/build-and-test.yml/badge.svg)](https://github.com/brndnmtthws/genserver/actions/workflows/build-and-test.yml) [![Codecov](https://img.shields.io/codecov/c/github/brndnmtthws/genserver)](https://app.codecov.io/gh/brndnmtthws/genserver/)\n\n# genserver: generate a generic server\n\ngenserver is tiny async actor framework, inspired by [Elixir's\nGenServer](https://hexdocs.pm/elixir/GenServer.html). With few lines code, we do\ngreat things.\n\nCheck out [the docs](https://docs.rs/genserver) for more details.\n\nThis library is a great choice if you need an small async actor framework that\ndoesn't get up in your face and has the features you need without all the cruft\nyou don't. This crate has the added advantage of being insanely fast, and comes\nwith all of Rust's safety features.\n\nThis code is 100% pure-Rust, with no unsafe code anywhere. It has minimal\ndependencies to keep your compile times short.\n\nEvery server you make and launch with the `GenServer` trait will spawn its own\nloop to handle incoming messages. You can make as many servers as you'd like,\nand they can all talk to each other by keeping a copy of the registry generated\nwith `#[make_registry{}]`. The registry can be cloned into different threads,\nand it's safe to send messages from anywhere within the same runtime.\n\n## Synopsis\n\nFirst, add the crate as a dependency:\n\n```console\ncargo add genserver\n```\n\nThen, try this code here in your crate (note the 2 features that need to be\nenabled in `main.rs` or `lib.rs` for applications and libraries respectively):\n\n```rust\n// these two features must be enabled at the crate level\n#![feature(type_alias_impl_trait, impl_trait_in_assoc_type)]\n\nuse std::future::Future;\n\nuse genserver::{make_registry, GenServer};\n\nstruct MyServer {\n    // Any state your server needs can go right\n    // in here. We keep a registry around in case\n    // we want to call any other servers from our\n    // server.\n    registry: MyRegistry,\n}\n\nimpl GenServer for MyServer {\n    // Message type for this server.\n    type Message = String;\n    // The type of the registry defined by the `make_registry` attribute macro.\n    type Registry = MyRegistry;\n    // The response type for calls.\n    type Response = String;\n\n    // The call response type, a future, which returns Self::Response.\n    type CallResponse\u003c'a\u003e = impl Future\u003cOutput = Self::Response\u003e + 'a;\n    // The cast response type, also a future, which returns unit.\n    type CastResponse\u003c'a\u003e = impl Future\u003cOutput = ()\u003e + 'a;\n\n    fn new(registry: Self::Registry) -\u003e Self {\n        // When are server is started, the registry passes a copy\n        // of itself here. We keep it around so we can call\n        // other servers from this one.\n        Self { registry }\n    }\n\n    // Calls to handle_call will block until our `Response` is returned.\n    // Because they return a future, we can return an async block here.\n    fn handle_call(\u0026mut self, message: Self::Message) -\u003e Self::CallResponse\u003c'_\u003e {\n        println!(\"handle_call received {}\", message);\n        std::future::ready(\"returned from handle_call\".into())\n    }\n\n    // Casts always return (), because they do not block callers and return\n    // immediately.\n    fn handle_cast(\u0026mut self, message: Self::Message) -\u003e Self::CastResponse\u003c'_\u003e {\n        println!(\"handle_cast received {}\", message);\n        std::future::ready(())\n    }\n}\n\n#[make_registry{\n    myserver: MyServer\n}]\nstruct MyRegistry;\n\n// When the registry goes out of scope, everything will shut down. You have to\n// keep the registry in scope as long as you want it to continue running.\ntokio::spawn(async {\n    let registry = MyRegistry::start().await;\n\n    let response = registry\n        .call_myserver(\"calling myserver\".into())\n        .await\n        .unwrap();\n    registry\n        .cast_myserver(\"casting to myserver\".into())\n        .await\n        .unwrap();\n    \n    // Give some time for the messages to be delivered.\n    tokio::time::sleep(Duration::from_secs(1)).await;\n});\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrndnmtthws%2Fgenserver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbrndnmtthws%2Fgenserver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrndnmtthws%2Fgenserver/lists"}