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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
//! This module defines macros for actor regsistration and invocation.
//!
//!
//
//!
//
///This macro defines a new actor instance in the system. It takes a literal string as
///actor name and an implmentation of [Producer](crate::common::actor::Producer) that is
///called to return an [Actor](crate::common::actor::Actor). The actor becomes active
///as soon as it is defined and receives a startup signal.
///
///
///Example
///
///```
///use arrows::{Actor, Addr, Mail, Msg, Producer};
///use serde::{Deserialize, Serialize};
///
///pub struct NewActor;
///
///impl Actor for NewActor {
/// fn receive(&mut self, _incoming: Mail) -> Option<Mail> {
/// Some(Msg::from_text("Reply from new actor").into())
/// }
///}
///
///```
///
///Next we implement the [Producer](crate::Producer) trait to produce `NewActor`
///intances on demand.
///
///```
///#[derive(Debug, Serialize, Deserialize, Default)]
///struct NewProducer;
///
///impl Producer for NewProducer {
/// fn produce(&mut self) -> Box<dyn Actor> {
/// Box::new(NewActor)
/// }
///}
///
///````
///At this point - we have our `Actor` and `Producer` implementations ready. we can use
///the `define_actor` macro to register an actor instance in the system. The producer will
///be called to return an actor instance and the producer itself would would be persisted
///in the system, the actor will be activated and would receive a post start signal. Same
///prodcer instance would be called to create instances of the actor at system restart/actor
///activation points at different times in the actor's life-cycle.
///
///```
///use arrows::define_actor;
///
///let actor_producer = NewProducer::default();
///define_actor!("new_actor", actor_producer);
///
///```
///At this stage, the actor would have received a start up signal and be ready to process
///messages.
///
///```
///use arrows::send;
///
///let m1 = Msg::from_text("Message to new_actor");
///let m2 = Msg::from_text("Message to new_actor");
///let m3 = Msg::from_text("Message to new_actor");
///send!("new_actor", (m1, m2, m3));
///
///```
///
///We can use same producer definition to create multiple instances of the actor.
///
///```
///let producer2 = NewProducer::default();
///let producer3 = NewProducer::default();
///define_actor!("another_actor", producer2);
///define_actor!("yet_another_actor", producer3);
///
///```
///
///
///Sends one or more messages to one or more actors defined in the system. This function is
///responsible for gathering and dispatching messages received from the macro invocation
///of `send!`. Multiple messages can be grouped for one more actors in one `send!` macro
///invocation as shown below:
///
///Example
///
///```
///use arrows::send;
///use arrows::Msg;
///
///let m1 = Msg::with_text("Message to actor1");
///let m2 = Msg::with_text("Message to actor1");
///let m3 = Msg::with_text("Message to actor2");
///let m4 = Msg::with_text("Message to actor1");
///let m5 = Msg::with_text("Message to actor1");
///send!("actor1", (m1, m2), "actor2", (m3), "actor1", (m4, m5));
///```
///Grouping within braces is not necessary while sending only to one actor:
///
///```
///let m6 = Msg::with_text("Message to actor3")
///let m7 = Msg::with_text("Message to actor3")
///send!("actor3", m6, m7);
///
///```
///Actors identified with string literal such as 'actor3' is assumed to be running in the
///local system(they would be resurrected - if they are not - on message send).
///
///Actors running in remote systems - need to be identified by the `Addr` construct:
///
///```
///use arrows::Addr;
///
///let remote_addr1 = Addr::remote("actor1", "10.10.10.10:7171");
///let remote_addr2 = Addr::remote("actor2", "11.11.11.11:8181");
///
///let m1 = Msg::with_text("Message to remote actor1");
///let m2 = Msg::with_text("Message to remote actor1");
///let m3 = Msg::with_text("Message to remote actor2");
///let m4 = Msg::with_text("Message to remote actor2");
///
///send!(remote_addr1, (m1,m2), remote_addr2, (m3,m4));
///
///```
;
=> ;
=> ;
=> ;
=> ;
=> ;
=> ;
=> ;
}