All Projects → fdeantoni → tiny-tokio-actor

fdeantoni / tiny-tokio-actor

Licence: Apache-2.0 License
A simple tiny actor library on top of Tokio

Programming Languages

rust
11053 projects

Projects that are alternatives of or similar to tiny-tokio-actor

meio
Rust actors alternative to Erlang/OTP
Stars: ✭ 152 (+442.86%)
Mutual labels:  actors, tokio
Coerce Rs
Coerce - an asynchronous (async/await) Actor runtime and cluster framework for Rust
Stars: ✭ 231 (+725%)
Mutual labels:  actors, tokio
xoom-cluster
The VLINGO XOOM platform SDK cluster management for Reactive, scalable resiliency of JVM tools and applications running on XOOM LATTICE and XOOM ACTORS.
Stars: ✭ 25 (-10.71%)
Mutual labels:  actors
rust-cardano-ouroboros-network
Rust implementation of networking layer for the Ouroboros blockchain protocol using Tokio framework.
Stars: ✭ 31 (+10.71%)
Mutual labels:  tokio
akka-http-streaming-response-examples
A list of examples that involve streaming with Akka Streams and used together with Akka HTTP
Stars: ✭ 73 (+160.71%)
Mutual labels:  actors
nano-rs
An implementation of Nano in Rust using Tokio
Stars: ✭ 29 (+3.57%)
Mutual labels:  tokio
theater
Actor framework for Dart. This package makes it easier to work with isolates, create clusters of isolates.
Stars: ✭ 29 (+3.57%)
Mutual labels:  actors
MuezzinAPI
A web server application for Islamic prayer times
Stars: ✭ 33 (+17.86%)
Mutual labels:  actors
transit
Massively real-time city transit streaming application
Stars: ✭ 20 (-28.57%)
Mutual labels:  actors
twitchchat
interface to the irc portion of Twitch's chat
Stars: ✭ 80 (+185.71%)
Mutual labels:  tokio
blockbuster
The Machinima Studio mod
Stars: ✭ 108 (+285.71%)
Mutual labels:  actors
protoactor-go
Proto Actor - Ultra fast distributed actors for Go, C# and Java/Kotlin
Stars: ✭ 4,138 (+14678.57%)
Mutual labels:  actors
nitox
Tokio-based async NATS client
Stars: ✭ 60 (+114.29%)
Mutual labels:  tokio
gen browser
Transparent bi-directional communication for clients, servers and more
Stars: ✭ 67 (+139.29%)
Mutual labels:  actors
wash
WAsmcloud SHell - A multi-tool for various wasmCloud activities.
Stars: ✭ 80 (+185.71%)
Mutual labels:  actors
tokio-tun
Asynchronous allocation of TUN/TAP devices in Rust using tokio
Stars: ✭ 17 (-39.29%)
Mutual labels:  tokio
the movie app open source
🎬 an app that lists movies in theaters and that will be released, and their respective actors using the api of the movie database, made with Flutter using Modular and MobX
Stars: ✭ 29 (+3.57%)
Mutual labels:  actors
nact
nact ⇒ node.js + actors ⇒ your services have never been so µ
Stars: ✭ 1,003 (+3482.14%)
Mutual labels:  actors
vxrifa
Utility library for Vert.X that allows using strong-typed interfaces in communication through EventBus
Stars: ✭ 15 (-46.43%)
Mutual labels:  actors
reacted
Actor based reactive java framework for microservices in local and distributed environment
Stars: ✭ 17 (-39.29%)
Mutual labels:  actors

Tiny Tokio Actor

crates.io build

Another actor library! Why another? I really like the actor model for development, and wanted something simple I could use on top of tokio.

[dependencies]
tiny-tokio-actor = "0.3"

Lets define an actor. First import the necessary crate:

use tiny_tokio_actor::*;

Next define the message we will be sending on the actor system's message bus:

// Define the system event bus message
#[derive(Clone, Debug)]
struct TestEvent(String);

impl SystemEvent for TestEvent {}

Next define the actor struct. The actor struct must be Send + Sync but need not be Clone. When implementing the Actor trait, you can override the default pre_start(), pre_restart(), and post_stop() methods:

struct TestActor {
    counter: usize
}

#[async_trait]
impl Actor<TestEvent> for TestActor {

    // This actor will immediately retry 5 times if it fails to start
    fn supervision_strategy() -> SupervisionStrategy {
        let strategy = supervision::NoIntervalStrategy::new(5);
        SupervisionStrategy::Retry(Box::new(strategy))
    }

    async fn pre_start(&mut self, ctx: &mut ActorContext<TestEvent>) -> Result<(), ActorError> {
        ctx.system.publish(TestEvent(format!("Actor '{}' started.", ctx.path)));
        Ok(())
    }

    async fn pre_restart(&mut self, ctx: &mut ActorContext<TestEvent>, error: Option<&ActorError>) -> Result<(), ActorError> {
        log::error!("Actor '{}' is restarting due to {:#?}", ctx.path, error);
        self.pre_start(ctx).await
    }

    async fn post_stop(&mut self, ctx: &mut ActorContext<TestEvent>) {
        ctx.system.publish(TestEvent(format!("Actor '{}' stopped.", ctx.path)));
    }
}

Next define a message you want the actor to handle. Note that you also define the response you expect back from the actor. If you do not want a resposne back you can simpy use () as response type.

#[derive(Clone, Debug)]
struct TestMessage(String);

impl Message for TestMessage {
    type Response = String;
}

Now implement the behaviour we want from the actor when we receive the message:

#[async_trait]
impl Handler<TestEvent, TestMessage> for TestActor {
    async fn handle(&mut self, msg: TestMessage, ctx: &mut ActorContext<TestEvent>) -> String {
        ctx.system.publish(TestEvent(format!("Message {} received by '{}'", &msg, ctx.path)));
        self.counter += 1;
        "Ping!".to_string()
    }
}

You can define more messages and behaviours you want the actor to handle. For example, lets define an OtherMessage we will let our actor handle:

#[derive(Clone, Debug)]
struct OtherMessage(usize);

impl Message for OtherMessage {
    type Response = usize;
}

// What the actor should do with the other message
#[async_trait]
impl Handler<TestEvent, OtherMessage> for TestActor {
    async fn handle(&mut self, msg: OtherMessage, ctx: &mut ActorContext<TestEvent>) -> usize {
        ctx.system.publish(TestEvent(format!("Message {} received by '{}'", &msg, ctx.path)));
        self.counter += msg.0;
        self.counter
    }
}

We can now test out our actor and send the two message types to it:

#[tokio::test]
async fn multi_message() {
    if std::env::var("RUST_LOG").is_err() {
        std::env::set_var("RUST_LOG", "trace");
    }
    let _ = env_logger::builder().is_test(true).try_init();

    let actor = TestActor { counter: 0 };

    let bus = EventBus::<TestEvent>::new(1000);
    let system = ActorSystem::new("test", bus);
    let actor_ref = system.create_actor("test-actor", actor).await.unwrap();

    let mut events = system.events();
    tokio::spawn(async move {
        loop {
            match events.recv().await {
                Ok(event) => println!("Received event! {:?}", event),
                Err(err) => println!("Error receivng event!!! {:?}", err)
            }
        }
    });

    tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;

    let msg_a = TestMessage("hello world!".to_string());
    let response_a = actor_ref.ask(msg_a).await.unwrap();
    assert_eq!(response_a, "Ping!".to_string());

    let msg_b = OtherMessage(10);
    let response_b = actor_ref.ask(msg_b).await.unwrap();
    assert_eq!(response_b, 11);
}

So basically this library provides:

  • An actor system with a message bus
  • A strongly typed actor with one or more message handlers
  • Actors referenced through ActorPaths and ActorRefs

See the docs, examples, and integration tests for more detailed examples.

Library is still incubating! There is still a lot to be done and the API is still unstable! The todo list so far:

  • Supervisor hierarchy
  • Create macros to make the defining of actors a lot simpler

Projects / blog posts that are worth checking out:

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].