{"id":15056348,"url":"https://github.com/dtzxporter/hydra","last_synced_at":"2025-04-06T22:07:52.309Z","repository":{"id":239039936,"uuid":"773215753","full_name":"dtzxporter/hydra","owner":"dtzxporter","description":"A framework for writing fault tolerant, highly scalable applications with the Rust programming language.","archived":false,"fork":false,"pushed_at":"2024-06-30T18:25:00.000Z","size":486,"stargazers_count":106,"open_issues_count":1,"forks_count":1,"subscribers_count":5,"default_branch":"main","last_synced_at":"2024-10-30T02:36:46.926Z","etag":null,"topics":["actors","elixir","erlang","rust","tokio"],"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/dtzxporter.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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}},"created_at":"2024-03-17T03:35:06.000Z","updated_at":"2024-10-27T13:15:05.000Z","dependencies_parsed_at":"2024-05-27T23:41:16.450Z","dependency_job_id":"f246a00d-1859-46d2-95e8-7f40e085d3a9","html_url":"https://github.com/dtzxporter/hydra","commit_stats":{"total_commits":239,"total_committers":1,"mean_commits":239.0,"dds":0.0,"last_synced_commit":"92678bafd115e71f99b8126106f93ad48c6c03c3"},"previous_names":["dtzxporter/hydra"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dtzxporter%2Fhydra","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dtzxporter%2Fhydra/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dtzxporter%2Fhydra/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dtzxporter%2Fhydra/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dtzxporter","download_url":"https://codeload.github.com/dtzxporter/hydra/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247557767,"owners_count":20958047,"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","elixir","erlang","rust","tokio"],"created_at":"2024-09-24T21:50:03.251Z","updated_at":"2025-04-06T22:07:52.282Z","avatar_url":"https://github.com/dtzxporter.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# \u003cimg src=\"https://raw.githubusercontent.com/dtzxporter/hydra/main/.github/hydra.png\" width=\"32\" height=\"32\"\u003e Hydra\n \nA framework for writing fault tolerant, highly scalable applications with the Rust programming language. It is:\n\n- **Fast**: Native performance powered by Tokio's light weight task architecture.\n- **Scalable**: All Hydra code runs inside lightweight threads of execution (called `Processes`) that are isolated and exchange information via messages.\n- **Fault-Tolerant**: Inspired by Erlang/Elixir's OTP, Hydra provides many of the same concepts like `GenServer` and `Supervisor` to restart parts of your system when things to awry.\n- **Distributed**: Hydra provides built-in support for running a fully distributed cluster of processes over a network of any size.\n\n[![Crates.io][crates-badge]][crates-url]\n[![Docs.rs][docs-badge]][docs-url]\n[![MIT licensed][mit-badge]][mit-url]\n[![Build Status][actions-badge]][actions-url]\n\n[crates-badge]: https://img.shields.io/crates/v/hydra.svg\n[crates-url]: https://crates.io/crates/hydra\n[docs-badge]: https://img.shields.io/docsrs/hydra/latest\n[docs-url]: https://docs.rs/hydra\n[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg\n[mit-url]: https://github.com/dtzxporter/hydra/blob/main/LICENSE\n[actions-badge]: https://github.com/dtzxporter/hydra/workflows/CI/badge.svg\n[actions-url]: https://github.com/dtzxporter/hydra/actions/workflows/ci.yml?query=branch%3Amain++\n\n## Overview\nHydra runs on the [Tokio](https://github.com/tokio-rs/tokio) runtime, known for powering reliable, asynchronous, and slim applications with the Rust programming language. At a high level, Hydra provides the following major components:\n\n- **Process**: A light weight task that supports sending and receiving messages.\n- **GenServer**: A generic server process that provides request/reply and state management.\n- **Supervisor**: A process which supervises other processes, used to provide fault-tolerance and encapsulate how our applications start and shutdown (gracefully).\n- **Registry**: A process which acts as a centralized 'registry' of processes allowing you to lookup running processes by any key.\n- **Node**: A mechanism to connect multiple nodes (instances) of Hydra together and monitor those connections.\n\n## Example\nA basic `GenServer` Stack application with Hydra.\n\nMake sure you have added Hydra, Serde in your Cargo.toml:\n```toml\n[dependencies]\nhydra = \"0.1\"\nserde = { version=\"1.0\", features = \"derive\" }\n```\n\nMake sure that you are **not** aborting on panics, Hydra catches and manages panics for all `Processes`. Find and **remove** this line if it exists in your Cargo.toml:\n```toml\npanic = \"abort\"\n```\n\nThen, in your main.rs:\n```rust\nuse hydra::Application;\nuse hydra::ExitReason;\nuse hydra::From;\nuse hydra::GenServer;\nuse hydra::GenServerOptions;\nuse hydra::Pid;\n\nuse serde::Deserialize;\nuse serde::Serialize;\n\n#[derive(Debug, Serialize, Deserialize)]\nenum StackMessage {\n    Pop,\n    PopResult(String),\n    Push(String),\n}\n\nstruct Stack {\n    stack: Vec\u003cString\u003e,\n}\n\nimpl Stack {\n    pub fn with_entries(entries: Vec\u003c\u0026'static str\u003e) -\u003e Self {\n        Self {\n            stack: Vec::from_iter(entries.into_iter().map(Into::into)),\n        }\n    }\n}\n\nimpl GenServer for Stack {\n    type Message = StackMessage;\n\n    async fn init(\u0026mut self) -\u003e Result\u003c(), ExitReason\u003e {\n        Ok(())\n    }\n\n    async fn handle_call(\n        \u0026mut self,\n        message: Self::Message,\n        _from: From,\n    ) -\u003e Result\u003cOption\u003cSelf::Message\u003e, ExitReason\u003e {\n        match message {\n            StackMessage::Pop =\u003e Ok(Some(StackMessage::PopResult(self.stack.remove(0)))),\n            _ =\u003e unreachable!(),\n        }\n    }\n\n    async fn handle_cast(\u0026mut self, message: Self::Message) -\u003e Result\u003c(), ExitReason\u003e {\n        match message {\n            StackMessage::Push(value) =\u003e self.stack.insert(0, value),\n            _ =\u003e unreachable!(),\n        }\n        Ok(())\n    }\n}\n\nstruct StackApplication;\n\nimpl Application for StackApplication {\n    // Here, we must link a process for the application to monitor, usually, a Supervisor, but it can be any process.\n    async fn start(\u0026self) -\u003e Result\u003cPid, ExitReason\u003e {\n        let pid = Stack::with_entries(vec![\"hello\", \"world\"])\n            .start_link(GenServerOptions::new())\n            .await\n            .expect(\"Failed to start stack!\");\n\n        let result = Stack::call(pid, StackMessage::Pop, None)\n            .await\n            .expect(\"Stack call failed!\");\n\n        tracing::info!(\"{:?}\", result);\n\n        Stack::cast(pid, StackMessage::Push(String::from(\"rust\")));\n\n        let result = Stack::call(pid, StackMessage::Pop, None)\n            .await\n            .expect(\"Stack call failed!\");\n\n        tracing::info!(\"{:?}\", result);\n\n        // Otherwise, the application will run forever waiting for Stack to terminate.\n        Stack::stop(pid, ExitReason::Normal, None).await?;\n\n        Ok(pid)\n    }\n}\n\nfn main() {\n    // This method will return once the linked Process in StackApplication::start has terminated.\n    Application::run(StackApplication)\n}\n```\n\nFind more examples in the [examples](https://github.com/dtzxporter/hydra/tree/main/hydra/examples) folder. You can run them with: `cargo run --example=stack`.\n\n## Related Projects\nThe following projects are related to, or in use in Hydra such that it would be wise to learn them as well:\n\n* [`tokio`]: A runtime for writing reliable, asynchronous, and slim applications with the Rust programming language.\n* [`serde`]: A framework for serializing and deserializing Rust data structures efficiently and generically.\n* [`tracing`]: A framework for application-level tracing and async-aware diagnostics.\n\n[`tokio`]: https://github.com/tokio-rs/tokio\n[`serde`]: https://github.com/serde-rs/serde\n[`tracing`]: https://github.com/tokio-rs/tracing\n\n## Changelog\n[View Changelog](https://github.com/dtzxporter/hydra/blob/main/CHANGELOG.md)\n\n## Benchmark\nThere is a message passing benchmark in the examples you can run using `cargo run --example=benchmark --release`. I've gotten the following results:\n\n- **Intel 14700k**: 26257627 msg/s\n- **Intel 7700k**: 7332666 msg/s\n- **Apple M1 Max**: 5743765 msg/s\n\n## License\nThis project is licensed under the [MIT license](https://github.com/dtzxporter/hydra/blob/main/LICENSE)\n\n### Contribution\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Hydra by you, shall be licensed as MIT, without any additional terms or conditions.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdtzxporter%2Fhydra","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdtzxporter%2Fhydra","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdtzxporter%2Fhydra/lists"}