{"id":29824273,"url":"https://github.com/cwahn/theta","last_synced_at":"2026-04-15T10:00:53.595Z","repository":{"id":305428251,"uuid":"1022867947","full_name":"cwahn/theta","owner":"cwahn","description":"An async actor framework for Rust","archived":false,"fork":false,"pushed_at":"2026-04-13T05:32:16.000Z","size":1282,"stargazers_count":62,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-04-13T07:24:16.485Z","etag":null,"topics":[],"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/cwahn.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":"2025-07-20T02:41:09.000Z","updated_at":"2026-04-13T05:32:21.000Z","dependencies_parsed_at":"2025-07-20T04:09:09.498Z","dependency_job_id":"040b67fd-e041-4371-acc6-19a144ad48ea","html_url":"https://github.com/cwahn/theta","commit_stats":null,"previous_names":["cwahn/theta"],"tags_count":52,"template":false,"template_full_name":null,"purl":"pkg:github/cwahn/theta","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cwahn%2Ftheta","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cwahn%2Ftheta/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cwahn%2Ftheta/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cwahn%2Ftheta/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cwahn","download_url":"https://codeload.github.com/cwahn/theta/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cwahn%2Ftheta/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31835820,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-15T07:17:56.427Z","status":"ssl_error","status_checked_at":"2026-04-15T07:17:30.007Z","response_time":63,"last_error":"SSL_read: 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":[],"created_at":"2025-07-29T02:43:04.188Z","updated_at":"2026-04-15T10:00:53.584Z","avatar_url":"https://github.com/cwahn.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Crates.io](https://img.shields.io/crates/v/theta.svg)](https://crates.io/crates/theta)\n[![Documentation](https://docs.rs/theta/badge.svg)](https://docs.rs/theta)\n[![CI](https://github.com/cwahn/theta/actions/workflows/ci.yml/badge.svg)](https://github.com/cwahn/theta/actions/workflows/ci.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n# Theta\n\n**An actor framework for Rust**\n\n\n\u003cdiv align=\"center\"\u003e\n  \u003cp\u003eAny questions or idea?\u003c/p\u003e\n  \u003ca href=\"https://github.com/cwahn/theta/discussions\"\u003e\n    \u003cimg alt=\"Join GitHub Discussions\"\n         src=\"https://img.shields.io/static/v1?label=\u0026message=Join%20GitHub%20Discussions\u0026color=0969da\u0026style=flat\u0026logo=github\u0026logoColor=white\"\n         style=\"user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none;\"\u003e\n  \u003c/a\u003e\n\u003c/div\u003e\n\n\n## Overview\nTheta is an **ergonomic** yet **minimal** and **performant** application framework based on actor model.\n\n- **Async Actor**\n  - An actor instance is a very thin wrapper around a `tokio::task` and two MPMC channels.\n  - `ActorRef` is just a single pointer(MPMC sender).\n- **Built-in remote**\n  - Distributed actor system powered by P2P network, `iroh`.\n  - Even `ActorRef` could be passed across network boundary as regular data in message.\n  - Available with feature `remote`.\n- **Built-in monitoring**\n  - \"Monitor\" suggested by Carl Hewitt's Actor Model is implemented as (possibly remote) monitoring feature.\n  - Available with feature `monitor`.\n- **Built-in persistence**\n  - Seamless respawn of actor from snapshot on file system, AWS S3 etc.\n  - Available with feature `persistence`.\n- **WASM/Browser support**\n  - See `examples/web-chat/` for a working P2P chat demo.\n\n\u003c!-- ## Motivation\nRust is powerful language with full control over low-level details, but raw threads and tasks are very fragile and error-prone. A couple different kinds of threads and tasks with synchronization primitives are managable, but what if there are tens or hundreds of them? Can you be sure there is no deadlock or starvation? Even if you can, what about your team and community? Lastly would it be flexible enough to respond to evolving demands or the users? --\u003e\n\n## Example\n```sh\ncargo add theta\n```\n\n```rust\nuse serde::{Deserialize, Serialize};\nuse theta::prelude::*;\n\n#[derive(Debug, Clone, ActorArgs)]\nstruct Counter {\n    value: i64,\n}\n\n#[derive(Debug, Clone, Serialize, Deserialize)]\npub struct GetValue;\n\n#[actor(\"96d9901f-24fc-4d82-8eb8-023153d41074\")]\nimpl Actor for Counter {\n    type View = Nil;\n\n    // Behaviors will generate single enum Msg for the actor\n    const _: () = async |amount: i64| {\n        self.value += amount;\n    };\n\n    const _: () = async |_: GetValue| -\u003e i64 { self.value };\n}\n\n#[tokio::main]\nasync fn main() -\u003e anyhow::Result\u003c()\u003e {\n    let ctx = RootContext::init_local();\n    let counter = ctx.spawn(Counter { value: 0 });\n\n    let _ = counter.tell(5); // Fire-and-forget\n\n    let current = counter.ask(GetValue).await?; // Wait for response\n    println!(\"Current value: {current}\");       // Current value: 5\n\n    Ok(())\n}\n```\n\n\n## 🚧 WIP\nTheta is currently under active development and API is subject to change. Not yet recommended for any serious business.\n### Todo\n- Core\n  - [x] Make `Result::Err` implementing `std::fmt::Display` on `tell` to be logged as `tracing::error!` to prevent silent failure or code duplication\n  - [x] Use concurrent hashmap\n  - [ ] Fix duplicated removing disconnected peer message\n- Macros\n  - [ ] Make `actor` macro to take identifier as `ActorId`\n- Supervision\n  - [ ] Factor out supervision as a optional feature\n- Remote\n  - [x] Define lifetime behavior of exported actors (Currently, exported actor will never get dropped)\n  - [x] Deduplicate simultanious connection attempt to each other\n  - [ ] Support full NodeAddr including Url format definition and sharing routing information between peers\n- Persistence\n  - [x] Cover partial persistence case; some could be stored in storage, but some data should be passed in runtime\n  - [x] Have respawn API to take closure, not value.\n- Actor pool\n  - [ ] Actor pool (task stealing with anonymous dynamic actors and MPMC)\n\n## License\n\nLicensed under the [MIT License](LICENSE).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcwahn%2Ftheta","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcwahn%2Ftheta","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcwahn%2Ftheta/lists"}