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 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
#![cfg_attr(docsrs, feature(doc_cfg))]
#![warn(
missing_debug_implementations,
rust_2018_idioms,
missing_docs,
unreachable_pub
)]
#![warn(clippy::pedantic)]
#![allow(clippy::module_name_repetitions)]
// Seems to be broken right now: https://github.com/rust-lang/rust-clippy/issues/8300
#![allow(clippy::no_effect_underscore_binding)]
//! `messages` is a runtime-agnostic actor library.
//!
//! It is heavily inspired by [`actix`][actix], a great actor framework.
//!
//! This crate can be used with any runtime, whether it popular or not.
//! However, for the biggest one (`tokio` and `async-std`) there is an optional
//! built-in support enabling more convenient interface (such as an automatic
//! actor spawning).
//!
//! [actix]: https://crates.io/crates/actix
//!
//! ## Asyncness
//!
//! In order to provide convenient interface, this crate uses [`async_trait`](https://docs.rs/async-trait/)
//! to declare traits with `async` methods.
//! To make the experience more convenient, `async_trait::async_trait` macro is publicly re-exported
//! in the [`prelude`] module.
//!
//! ## Examples
//!
//! ### With runtime features
//!
//! ```rust
//! use messages::prelude::*;
//!
//! struct Example; // Most of the types can be an actor.
//!
//! // While `Actor` implementation can be customized, it is not required.
//! #[async_trait]
//! impl Actor for Example {}
//!
//! // Message handler that calculated sum of two numbers.
//! #[async_trait]
//! impl Handler<(u8, u8)> for Example {
//! type Result = u16;
//! async fn handle(&mut self, (a, b): (u8, u8), context: &Context<Self>) -> u16 {
//! (a as u16) + (b as u16)
//! }
//! }
//!
//! // Notification handler that calculated just writes received number to stdout.
//! #[async_trait]
//! impl Notifiable<u8> for Example {
//! async fn notify(&mut self, input: u8, context: &Context<Self>) {
//! println!("Received number {}", input);
//! }
//! }
//!
//! #[tokio::main]
//! async fn main() {
//! let mut addr = Example.spawn();
//! let result = addr.send((22, 20)).await.unwrap();
//! assert_eq!(result, 42);
//! addr.notify(42).await.unwrap();
//! addr.stop().await;
//! addr.wait_for_stop().await;
//! }
//! ```
//!
//! ### Without runtime features
//!
//! ```rust
//! use messages::prelude::*;
//!
//! struct Ping;
//!
//! #[async_trait]
//! impl Actor for Ping {}
//!
//! #[async_trait]
//! impl Handler<u8> for Ping {
//! type Result = u8;
//! async fn handle(&mut self, input: u8, context: &Context<Self>) -> u8 {
//! input
//! }
//! }
//!
//! #[tokio::main]
//! async fn main() {
//! let context = Context::new();
//! let mut addr = context.address();
//! let actor = Ping;
//! // Could've been any other runtime.
//! let mut task_handle = tokio::spawn(context.run(actor));
//! let result = addr.send(42).await.unwrap();
//! assert_eq!(result, 42);
//! addr.stop().await;
//! addr.wait_for_stop().await;
//! task_handle.await.unwrap();
//! }
//! ```
//!
//! ## Main entities
//!
//! Main entites of this crate:
//!
//! - [`Actor`](crate::prelude::Actor): definition of an actor.
//! - [`Context`](crate::prelude::Context): execution context for an actor.
//! - [`Address`](crate::prelude::Address): address of an actor that is used to communicate with it.
//! - Handler traits: [`Handler`](crate::prelude::Handler) and [`Notifiable`](crate::prelude::Notifiable).
//!
//! With runtime features enabled, there are also several more points of interest:
//!
//! - [`Registry`](crate::prelude::Registry): Collection of independent, unique and named actors.
//! - [`Service`](crate::prelude::Service): Actor that can be stored in the registry.
//! - [`Coroutine`](crate::prelude::Coroutine): Alternative to the `Handler` trait that allows
//! parallel message processing.
//!
/// Collection of the main types required to work with `messages` crate.
pub mod prelude {
/// Convenience re-export of [`async_trait`](https://docs.rs/async-trait/) proc-macro.
pub use async_trait::async_trait;
pub use crate::{
actor::{Actor, ActorAction},
address::Address,
context::Context,
errors::SendError,
handler::{Handler, Notifiable},
};
super::cfg_runtime! {
pub use crate::registry::{Service, Registry};
pub use crate::actor::RuntimeActorExt;
pub use crate::handler::Coroutine;
/// Re-export of `JoinHandle` of chosen runtime.
#[cfg_attr(not(docsrs), doc(hidden))]
// ^ Kludge: `cargo deadlinks` finds a broken link in the tokio docs,
// and currently it's not possible to ignore that error.
// However, we don't want to completely hide this element.
pub use crate::runtime::JoinHandle;
}
}
pub mod actor;
pub mod address;
pub mod context;
pub mod errors;
pub mod handler;
cfg_runtime! {
pub mod registry;
}
mod envelope;
mod runtime;