1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
//! A Simple Tiny Tokio Actor Crate
//!
//! This crate provides a minimally functioning actor system with a common
//! event bus. Tokio unbounded channels are used for the mailbox of the
//! actors, and actor behaviour (defined through the `Handler` trait) can
//! use the request+response pattern (using tokio oneshot channel for
//! responses). You an send messages to actors either through a `tell`
//! where the method does not provide a response, or an `ask`. The `ask`
//! method does provide a response
//!
//! Example
//! ```
//! use tiny_tokio_actor::*;
//!
//! // The event message you may want to publish to the system event bus.
//! #[derive(Clone, Debug)]
//! struct TestEvent(String);
//!
//! // Mark the struct as a system event message.
//! impl SystemEvent for TestEvent {}
//!
//! // The actor struct must derive Clone.
//! #[derive(Clone)]
//! struct TestActor {
//! counter: usize
//! }
//!
//! // Mark the struct as an actor.
//! impl Actor<TestEvent> for TestActor {}
//!
//! // The message the actor will expect. It must derive Clone.
//! // Debug is not required.
//! #[derive(Clone, Debug)]
//! struct TestMessage(String);
//!
//! // Mark the message struct as an actor message. Note that we
//! // also define the response we expect back from this message.
//! // If no response is desired, just use `()`.
//! impl Message for TestMessage {
//! type Response = String;
//! }
//!
//! // Define the behaviour of the actor. Note that the `handle` method
//! // has a `String` return type because that is what we defined the
//! // Response to be of `TestMessage`. As the method is async, we have
//! // to annotate the implementation with the `async_trait` macro (a
//! // re-export of the async-trait crate).
//! #[async_trait]
//! impl Handler<TestEvent, TestMessage> for TestActor {
//! async fn handle(&mut self, msg: TestMessage, ctx: &mut ActorContext<TestEvent>) -> String {
//! self.counter += 1;
//! ctx.system.publish(TestEvent(format!("message received by '{}'", ctx.path)));
//! "Ping!".to_string()
//! }
//! }
//!
//! #[tokio::main]
//! pub async fn main() -> Result<(), ActorError> {
//!
//! // Create the actor
//! let actor = TestActor { counter: 0 };
//! // Create the message we will send
//! let msg = TestMessage("hello world!".to_string());
//!
//! // Create the system event bus
//! let bus = EventBus::<TestEvent>::new(1000);
//! // Create the actor system with the event bus
//! let system = ActorSystem::new("test", bus);
//! // Launch the actor on the actor system
//! let mut actor_ref = system.create_actor("test-actor", actor).await?;
//!
//! // Listen for events on the system event bus
//! let mut events: EventReceiver<TestEvent> = system.events();
//! tokio::spawn(async move {
//! loop {
//! match events.recv().await {
//! Ok(event) => println!("Received event! {:?}", event),
//! Err(err) => println!("Error receivng event!!! {:?}", err)
//! }
//! }
//! });
//!
//! // Wait a little for the actor to start up
//! tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
//!
//! // Send the actor the message through an `ask` from which we will
//! // get a response
//! let response = actor_ref.ask(msg).await?;
//! println!("Response: {}", response);
//! Ok(())
//! }
//! ```
mod actor;
mod bus;
mod system;
pub use actor::{Actor, ActorRef, ActorPath, ActorError, ActorContext, Handler, Message};
pub use bus::{EventBus, EventReceiver};
pub use system::{ActorSystem, SystemEvent};
pub use async_trait::async_trait;