messages/lib.rs
1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![warn(
3 missing_debug_implementations,
4 rust_2018_idioms,
5 missing_docs,
6 unreachable_pub
7)]
8#![warn(clippy::pedantic)]
9#![allow(clippy::module_name_repetitions)]
10// Seems to be broken right now: https://github.com/rust-lang/rust-clippy/issues/8300
11#![allow(clippy::no_effect_underscore_binding)]
12
13//! `messages` is a runtime-agnostic actor library.
14//!
15//! It is heavily inspired by [`actix`][actix], a great actor framework.
16//!
17//! This crate can be used with any runtime, whether it popular or not.
18//! However, for the biggest one (`tokio` and `async-std`) there is an optional
19//! built-in support enabling more convenient interface (such as an automatic
20//! actor spawning).
21//!
22//! [actix]: https://crates.io/crates/actix
23//!
24//! ## Asyncness
25//!
26//! In order to provide convenient interface, this crate uses [`async_trait`](https://docs.rs/async-trait/)
27//! to declare traits with `async` methods.
28//! To make the experience more convenient, `async_trait::async_trait` macro is publicly re-exported
29//! in the [`prelude`] module.
30//!
31//! ## Examples
32//!
33//! ### With runtime features
34//!
35//! ```rust
36//! use messages::prelude::*;
37//!
38//! struct Example; // Most of the types can be an actor.
39//!
40//! // While `Actor` implementation can be customized, it is not required.
41//! #[async_trait]
42//! impl Actor for Example {}
43//!
44//! // Message handler that calculated sum of two numbers.
45//! #[async_trait]
46//! impl Handler<(u8, u8)> for Example {
47//! type Result = u16;
48//! async fn handle(&mut self, (a, b): (u8, u8), context: &Context<Self>) -> u16 {
49//! (a as u16) + (b as u16)
50//! }
51//! }
52//!
53//! // Notification handler that calculated just writes received number to stdout.
54//! #[async_trait]
55//! impl Notifiable<u8> for Example {
56//! async fn notify(&mut self, input: u8, context: &Context<Self>) {
57//! println!("Received number {}", input);
58//! }
59//! }
60//!
61//! #[tokio::main]
62//! async fn main() {
63//! let mut addr = Example.spawn();
64//! let result = addr.send((22, 20)).await.unwrap();
65//! assert_eq!(result, 42);
66//! addr.notify(42).await.unwrap();
67//! addr.stop().await;
68//! addr.wait_for_stop().await;
69//! }
70//! ```
71//!
72//! ### Without runtime features
73//!
74//! ```rust
75//! use messages::prelude::*;
76//!
77//! struct Ping;
78//!
79//! #[async_trait]
80//! impl Actor for Ping {}
81//!
82//! #[async_trait]
83//! impl Handler<u8> for Ping {
84//! type Result = u8;
85//! async fn handle(&mut self, input: u8, context: &Context<Self>) -> u8 {
86//! input
87//! }
88//! }
89//!
90//! #[tokio::main]
91//! async fn main() {
92//! let context = Context::new();
93//! let mut addr = context.address();
94//! let actor = Ping;
95//! // Could've been any other runtime.
96//! let mut task_handle = tokio::spawn(context.run(actor));
97//! let result = addr.send(42).await.unwrap();
98//! assert_eq!(result, 42);
99//! addr.stop().await;
100//! addr.wait_for_stop().await;
101//! task_handle.await.unwrap();
102//! }
103//! ```
104//!
105//! ## Main entities
106//!
107//! Main entites of this crate:
108//!
109//! - [`Actor`](crate::prelude::Actor): definition of an actor.
110//! - [`Context`](crate::prelude::Context): execution context for an actor.
111//! - [`Address`](crate::prelude::Address): address of an actor that is used to communicate with it.
112//! - Handler traits: [`Handler`](crate::prelude::Handler) and [`Notifiable`](crate::prelude::Notifiable).
113//!
114//! With runtime features enabled, there are also several more points of interest:
115//!
116//! - [`Registry`](crate::prelude::Registry): Collection of independent, unique and named actors.
117//! - [`Service`](crate::prelude::Service): Actor that can be stored in the registry.
118//! - [`Coroutine`](crate::prelude::Coroutine): Alternative to the `Handler` trait that allows
119//! parallel message processing.
120//!
121
122/// Collection of the main types required to work with `messages` crate.
123pub mod prelude {
124 /// Convenience re-export of [`async_trait`](https://docs.rs/async-trait/) proc-macro.
125 pub use async_trait::async_trait;
126
127 pub use crate::{
128 actor::{Actor, ActorAction},
129 address::Address,
130 context::Context,
131 errors::SendError,
132 handler::{Handler, Notifiable},
133 };
134
135 super::cfg_runtime! {
136 pub use crate::registry::{Service, Registry};
137 pub use crate::actor::RuntimeActorExt;
138 pub use crate::handler::Coroutine;
139
140 /// Re-export of `JoinHandle` of chosen runtime.
141 #[cfg_attr(not(docsrs), doc(hidden))]
142 // ^ Kludge: `cargo deadlinks` finds a broken link in the tokio docs,
143 // and currently it's not possible to ignore that error.
144 // However, we don't want to completely hide this element.
145 pub use crate::runtime::JoinHandle;
146 }
147}
148
149pub mod actor;
150pub mod address;
151pub mod context;
152pub mod errors;
153pub mod handler;
154
155cfg_runtime! {
156 pub mod registry;
157}
158
159mod envelope;
160mod runtime;