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;