theta

Crates.iotheta
lib.rstheta
version0.1.0-alpha.39
created_at2025-07-20 03:19:12.771054+00
updated_at2025-09-18 13:46:20.717534+00
descriptionAn Rust Actor Framework
homepage
repositoryhttps://github.com/cwahn/theta
max_upload_size
id1760738
size323,974
lighthouse (cwahn)

documentation

https://docs.rs/theta

README

Crates.io Documentation License: MIT

Theta

An async actor framework for Rust

Any questions or idea?

Join GitHub Discussions

Overview

Theta is an ergonomic yet minimal and performant async actor framework which Rust deserves.

  • Async
    • An actor instance is a very thin wrapper around a tokio::task and two MPMC channels.
    • ActorRef is just a MPMC sender.
  • Built-in remote
    • Distributed actor system powered by P2P network, iroh.
    • Even ActorRef could be passed around network boundary as regular data in message.
    • Available with feature remote.
  • Built-in monitoring
    • "Monitor" suggested by Carl Hewitt's Actor Model is implemented as (possibly remote) monitoring feature.
    • Available with feature monitor.
  • Built-in persistence
    • Seamless respawn of actor from snapshot on file system, AWS S3 etc.
    • Available with feature persistence.
  • WASM support (WIP)
    • Compile to WebAssembly for running in browser or other WASM environments

Example

cargo add theta
use serde::{Deserialize, Serialize};
use theta::prelude::*;

#[derive(Debug, Clone, ActorArgs)]
struct Counter {
    value: i64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Inc(i64);

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GetValue;

#[actor("96d9901f-24fc-4d82-8eb8-023153d41074")]
impl Actor for Counter {
    type View = Nil;

    // Behaviors will generate single enum Msg for the actor
    const _: () = {
        async |Inc(amount): Inc| { // Behavior can access &mut self
            self.value += amount;
        };

        async |_: GetValue| -> i64 {  // Behavior may or may not have return
            self.value 
        };
    };
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let ctx = RootContext::init_local();
    let counter = ctx.spawn(Counter { value: 0 });

    let _ = counter.tell(Inc(5)); // Fire-and-forget

    let current = counter.ask(GetValue).await?; // Wait for response
    println!("Current value: {current}"); // Current value: 5

    Ok(())
}

🚧 WIP

Theta is currently under active development and API is subject to change. Not yet recommended for any serious business.

Todo

  • Core
    • Make Result::Err implementing std::fmt::Display on tell to be logged as tracing::error! to prevent silent failure or code duplication
    • Deduplicate simultanious connection attempt to each other
    • Use concurrent hashmap
  • Macros
    • Make actor macro to take identifier as ActorId
  • Supervision
    • Factor out supervision as a optional feature
  • Remote
    • Define lifetime behavior of exported actors (Currently, exported actor will never get dropped)
    • Support full NodeAddr including Url format definition and sharing routing information between peers
    • Network timeout constants
  • Persistence
    • Cover partial persistence case; some could be stored in storage, but some data should be passed in runtime
    • Have respawn API to take closure, not value.
  • Actor pool
    • Actor pool (task stealing with anonymous dynamic actors and MPMC)

License

Licensed under the MIT License.

Commit count: 345

cargo fmt