Commit | Line | Data |
4536f655 |
1 | Stem Message Design Notes |
2 | |
3 | Stem Messages are how Cells communicate with each other. Messages are |
4 | simple data structures with two major sections: the address and the |
5 | content. The address contains the Cell name the message is directed to and |
6 | which Cell to send replies to. The content has the message type, command |
7 | and data. These sections are described below in further detail. |
8 | |
9 | The Message address section has multiple addresses called types. The two |
10 | supported types correspond to the common email headers and are called |
11 | 'to' and 'from'. The 'to' address designates which Cell will get this |
12 | message and the 'from' address says which Cell sent this message. Other |
13 | address types which may be supported are 'reply' (which overrides the |
14 | 'from' address for replies) and 'orig' which is the address of the |
15 | original Cell which created this message (useful when messages get |
16 | forwarded). Each address type contains the standard Stem Cell address |
17 | triplet of Hub/Cell/Target which are called the address parts. The Cell |
18 | name is required and the Hub and Target are optional. |
19 | |
20 | The Message content has information about this message and any data |
21 | being sent to the destination Cell. The primary attribute is 'type' |
22 | which can be set to any string, but common types are 'data', 'cmd', |
23 | 'response' and 'status'. Stem modules and Cells can create any Message |
24 | types they want. If the Message is a 'cmd' type, then the 'cmd' |
25 | attribute must be set to the command. A status type Message requires the |
26 | 'status' attribute be set and the 'data' or 'response' types has the |
27 | 'data' attribute set (though any message type can send data). There is |
28 | also a special flag attribute called 'ack_req' which forces a 'msg_ack' |
29 | type to be sent back to the 'from' address after this message is |
30 | delivered. One important note about the 'data' attribute, it is always a |
31 | reference and never a simple Perl scalar value. You can send a scalar |
32 | value but only by setting the 'data' attribute to its reference. |
33 | |
34 | Messages are constructed with the 'new' method of the Stem::Msg |
35 | class. Any of the message attributes can be specified in that call or |
36 | accessed/modified with the accessor methods. When a Message is completed |
37 | and ready to be sent, the dispatch method is called and the message is |
38 | queued for delivery. For convenience, the Message address types and part |
39 | can be combined into one attribute name in both the constructor and |
40 | accessors. So the Cell the message is directed at can be set with |
41 | 'to_cell' and the Hub it came from can be accessed with 'from_hub'. The |
42 | entire address triplet of an address type can be set or accessed just |
43 | with its type name, so the 'to' address is set or accessed with the 'to' |
44 | attribute or method. It takes or returns a hash of the address parts and |
45 | their values. |
46 | |
47 | Messages are delivered only after the current callback is finished |
48 | executing (remember all code in Stem are called as callbacks). Stem |
49 | Message delivery is the heart of Stem operations and is described in |
50 | detail here. Delivery take place in three phases, the first determining |
51 | which Hub the Message is sent to, the second, which Cell in that Hub |
52 | gets it, and the third, which method in that Cell to call for delivery. |
53 | |
54 | If the Message has a 'to_hub' address, then that Hub name is looked up |
55 | in the Portal (which are Cells which connect Hubs together) registry. If |
56 | a Portal is found, the Message is delivered to it to be sent to the |
57 | destination Hub for local delivery. A Message can be forwarded across |
58 | several Hubs before it gets delivered to its destination Cell. If the |
59 | Hub name is the same as the current Hub or there is no Hub name in the |
60 | address, the Message is delivered to a Cell in the current Hub. In the |
61 | special case where there is no Hub name and the Cell name isn't |
62 | registered in the current Hub, the Message is sent to the Portal with an |
63 | alias of DEFAULT. This is just like the default route in IP routing |
64 | tables. If there is a Hub name and the Cell is not found, then there is |
65 | an addressing error and that is logged and the Message is discarded. |
66 | |
67 | Once a Message's destination Hub is reached, it must be delivered to a |
68 | local Cell. The 'to_cell' and 'to_target' attributes are accessed from |
69 | the message and that pair is searched for in this Hub's Cell registry. |
70 | If there is no Target name in the address, it defaults to the null |
71 | string. If there is a Target and the Cell is not found, the search is |
72 | repeated with no Target name (the Target name will be used by the |
73 | destination Cell). If the Cell still is not found, an addressing error |
74 | will be logged (with the message address) and the Message is discarded. |
75 | |
76 | When the destination Cell of a Message is determined, the method to call |
77 | for delivery must be chosen. The rules for this are simple. If a Message |
78 | is a 'cmd' type, then the method name is made by taking the 'cmd' name |
79 | from that attribute and appending '_cmd' to it. So a 'foo' command |
80 | message will have its type set to 'cmd', the 'cmd' set to 'foo' and it |
81 | will be delivered to the 'foo_cmd' method. If the Message is any other |
82 | type than 'cmd' the method name is created by taking its type name and |
83 | appending '_in' to it. So a 'foo' type Message is delivered to the |
84 | method 'foo_in'. If the delivery method doesn't exist, the default |
85 | method 'msg_in' is used. If no delivery method is found, then an error |
86 | is logged and the Message is discarded. |
87 | |
88 | Command Messages have a useful feature where they can automatically |
89 | generate 'response' messages. When a 'cmd' delivery method is called and |
90 | it returns a defined value, a 'response' type Message is created using |
91 | the 'reply' Message method. This uses the 'reply' or 'from' address in |
92 | 'cmd' Message as the 'to' address in the 'response' Message. Its data |
93 | field is set from the data returned from the command delivery |
94 | method. This reduces the work of common command methods to just having |
95 | to return a data value. Many Cells use this technique, e.g. the |
96 | status_cmd method in a Cell just returns the status text of it. The |
97 | delivery mechanism takes that text and creates and dispatches a |
98 | 'response' method with the status text as its 'data' payload. |