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
//! Tyra is a [configurable](./prelude/struct.TyraConfig.html) typed actor framework
//!
//! An [Actor](./prelude/trait.Actor.html) is an object with which you can only interact by sending predefined [messages](./prelude/trait.ActorMessage.html)
//!
//! Furthermore Actors are bound to a thread pool and can be moved between executions to any of the threads of said pool.
//!
//! [crossbeam-channel](https://github.com/crossbeam-rs/crossbeam) and [flume](https://github.com/zesterer/flume) are used for all internal-messaging
//!
//! # Examples
//!
//! Basic usage:
//!
//! ```rust
//! use tyra::prelude::*;
//! use std::process::exit;
//! use std::time::Duration;
//! use std::error::Error;
//!
//! // define message
//! struct FooBar {}
//! impl ActorMessage for FooBar {}
//!
//! // define actor
//! struct HelloWorld {}
//! impl Actor for HelloWorld {}
//!
//! // setup required Factory
//! struct HelloWorldFactory {}
//! impl ActorFactory<HelloWorld> for HelloWorldFactory {
//! fn new_actor(&mut self, _context: ActorContext<HelloWorld>) -> Result<HelloWorld, Box<dyn Error>> {
//! Ok(HelloWorld {})
//! }
//! }
//!
//! // each supported message has its own Handler implementation
//! // this is where the actual work is done
//! impl Handler<FooBar> for HelloWorld {
//! fn handle(&mut self, _msg: FooBar, _context: &ActorContext<Self>) -> Result<ActorResult, Box<dyn Error>> {
//! println!("Message Received!");
//! Ok(ActorResult::Ok)
//! }
//! }
//!
//! fn main() {
//! // create a new actor system with the default config
//! let actor_config = TyraConfig::new().unwrap();
//! let actor_system = ActorSystem::new(actor_config);
//!
//! // create an actor and send it a message
//! let factory = HelloWorldFactory {};
//! let actor = actor_system
//! .builder()
//! .spawn("hello-world", factory)
//! .unwrap();
//! actor.send(FooBar {}).unwrap();
//!
//! // cleanup
//! actor.stop().unwrap();
//! actor_system.stop(Duration::from_millis(5000));
//! exit(actor_system.await_shutdown());
//! }
//! ```
//!
//! # Architecture
//!
//! ## User POV
//!
//! ```text
//! ┌──────────────────────┐
//! │ │
//! │ TyraConfig │
//! │ │
//! └──────────┬───────────┘
//! │
//! ┌───────▼───────┐
//! │ │
//! ┌────────────────┤ ActorSystem ├─────────────────┐
//! │ │ │ │
//! │ └───────┬───────┘ │
//! │ │ │
//! ┌────────▼─────────┐ ┌────────▼─────────┐ ┌─────────▼────────┐
//! │ │ │ │ │ │
//! │ ActorBuilder A │ │ ActorBuilder B │ │ ActorBuilder N │
//! │ │ │ │ │ │
//! └┬─────────────────┘ └┬─────────────────┘ └┬─────────────────┘
//! │ │ │
//! │ ┌────────────┐ │ ┌────────────┐ │ ┌────────────┐
//! │ │ │ │ │ │ │ │ │
//! ├─► Actor A1 │ ├──► Actor B1 │ ├──► Actor N1 │
//! │ │ │ │ │ │ │ │ │
//! │ └────────────┘ │ └────────────┘ │ └────────────┘
//! │ │ │
//! │ ┌────────────┐ │ ┌────────────┐ │ ┌────────────┐
//! │ │ │ │ │ │ │ │ │
//! ├─► Actor A2 │ ├──► Actor B2 │ ├──► Actor N2 │
//! │ │ │ │ │ │ │ │ │
//! │ └────────────┘ │ └────────────┘ │ └────────────┘
//! │ │ │
//! │ ┌────────────┐ │ ┌────────────┐ │ ┌────────────┐
//! │ │ │ │ │ │ │ │ │
//! └─► Actor An │ └──► Actor Bn │ └──► Actor Nn │
//! │ │ │ │ │ │
//! └────────────┘ └────────────┘ └────────────┘
//!
//! ```
//!
/// core components
/// collection of different router implementations