{"id":27185050,"url":"https://github.com/threefoldtech/rbus","last_synced_at":"2025-04-09T17:10:16.235Z","repository":{"id":40667397,"uuid":"430777265","full_name":"threefoldtech/rbus","owner":"threefoldtech","description":"experimental implementation of zbus in rust","archived":false,"fork":false,"pushed_at":"2023-10-12T09:42:33.000Z","size":68,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-04-30T08:06:31.393Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/threefoldtech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-11-22T16:10:59.000Z","updated_at":"2022-06-27T08:37:20.000Z","dependencies_parsed_at":"2022-08-10T00:23:36.644Z","dependency_job_id":null,"html_url":"https://github.com/threefoldtech/rbus","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/threefoldtech%2Frbus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/threefoldtech%2Frbus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/threefoldtech%2Frbus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/threefoldtech%2Frbus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/threefoldtech","download_url":"https://codeload.github.com/threefoldtech/rbus/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248074976,"owners_count":21043490,"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":[],"created_at":"2025-04-09T17:10:15.804Z","updated_at":"2025-04-09T17:10:16.229Z","avatar_url":"https://github.com/threefoldtech.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ZBUS\n[`zbus`](https://github.com/threefoldtech/zbus) implementation in rust (hence the name `rbus`). It ss a framework for `local` RPC calls. User of this protocol will enable separate processes to make rpc calls to each other without the knowledge of how to reach the other component directly or where it actually live on the system.\n\nThis is accomplished by using redis as a message bus. But calls still need to know:\n- the module name\n- object identity\n- method names that are allowed to be called over the bus\n- exact arguments number and types\n- exact return type(s)\n\n```\nmodule(name) {\n    object(name, version) {\n        method[name](arguments ...) -\u003e output\n    }\n    object(name, version) {\n        ...\n    }\n}\n```\n\nHence all implementers of this protocol usually provide tool set to generate both server and client stubs.\n\nWhile `rbus` provide you the tools to manually build server and client side stubs. It also provide you with a convenient macro to generate both server and client stubs\n\n```rust\nuse anyhow::Result;\nuse serde::{Deserialize, Serialize};\n\nuse rbus::object;\n\n// You can build your own complex object to pass around as\n// inputs and outputs as long as they are serder serializable\n\n#[derive(Serialize, Deserialize)]\npub struct Data {\n    binary: Vec\u003cu8\u003e,\n    str: String,\n}\n\n// annotate the service trait with `object` this will\n// generate a usable server and client stubs.\n// it accepts\n// - name [optional] default to trait name\n// - version [optional] default to 1.0\n//\n// NOTE:\n// - only trait methods with first argument as receiver will be available for RPC\n// - receiver must be a shared ref to self (\u0026self)\n// - all input arguments must be of type \u003cT: Serialize\u003e\n// - return must be a Result (any Result) as long as the E type can be stringfied \u003cE: Display\u003e\n// please check docs for `object` for more details\n#[object(name = \"calculator\", version = \"0.2\")]\npub trait Calculator {\n    // input and outputs can be anything according to the rules above\n    fn add(\u0026self, a: f64, b: f64) -\u003e anyhow::Result\u003c(f64, f64)\u003e;\n\n    // to be able to do calls across languages, you can rename\n    // the method (over wire) to be able to call methods in Golang\n    // for example\n    #[rename(\"Divide\")]\n    fn divide(\u0026self, a: f64, b: f64) -\u003e Result\u003cf64\u003e;\n    fn multiply(\u0026self, a: f64, b: f64) -\u003e Result\u003cf64\u003e;\n\n    // methods can be declared async.\n    async fn get_data(\u0026self) -\u003e Result\u003cData\u003e;\n}\n\n// some implementation of our trait\nstruct CalculatorImpl;\n\n/// async_trait is needed because we using async methods in tratis\n#[async_trait::async_trait]\nimpl Calculator for CalculatorImpl {\n    fn add(\u0026self, a: f64, b: f64) -\u003e Result\u003c(f64, f64)\u003e {\n        log::debug!(\"adding({}, {})\", a, b);\n        Ok((a + b, a - b))\n    }\n    fn divide(\u0026self, a: f64, b: f64) -\u003e Result\u003cf64\u003e {\n        if b == 0.0 {\n            anyhow::bail!(\"cannot divide by zero\")\n        }\n        Ok(a / b)\n    }\n    fn multiply(\u0026self, a: f64, b: f64) -\u003e Result\u003cf64\u003e {\n        Ok(a * b)\n    }\n    async fn get_data(\u0026self) -\u003e Result\u003cData\u003e {\n        Ok(Data {\n            binary: vec![],\n            str: \"Hello\".into(),\n        })\n    }\n}\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c()\u003e {\n    simple_logger::SimpleLogger::new()\n        .with_level(log::LevelFilter::Debug)\n        .init()\n        .unwrap();\n\n    let pool = rbus::pool(\"redis://localhost:6379\").await?;\n\n    let server = true;\n    if server {\n        // build the object dispatcher\n        let calc = CalculatorObject::from(CalculatorImpl);\n        // create the module (server)\n        let mut server = rbus::Server::new(pool, \"server\", 3).await?;\n        // register the object\n        server.register(calc);\n\n        println!(\"running server\");\n        server.run().await;\n    } else {\n        let client = rbus::Client::new(pool);\n\n        // same as CalculatorObject, the CalculatorStub is auto generated in\n        // this scope. Not the\n        let calc = CalculatorStub::new(\"server\", client);\n\n        println!(\"making calls\");\n        println!(\"add(1,2) =\u003e {:?}\", calc.add(1f64, 2f64).await);\n        println!(\"divide(10,3) =\u003e {:?}\", calc.divide(10f64, 3f64).await);\n        println!(\"divide(10,0) =\u003e {:?}\", calc.divide(10f64, 0f64).await);\n    }\n\n    Ok(())\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthreefoldtech%2Frbus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthreefoldtech%2Frbus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthreefoldtech%2Frbus/lists"}