cleaned up demo scripts locations
[urisagit/Stem.git] / Design / config_notes
1
2       Stem Object and Cell Creation and Configuration Design Notes
3
4 All Stem cells and objects share the same API style in their constructor
5 methods (commonly 'new'). All parameters are passed as key/value
6 attributes and processed with Stem::Class::parse_args which is driven
7 with a simple table of field descriptions. Each field is described by an
8 anonymous hash with attribute/values. Each allowed field must have a
9 name and it also can have several optional description attributes. Here
10 are the supported field description attributes:
11
12         name            The value of this is the name of this
13                         field. Obviously the field name is required.
14
15         required        This is a boolean value that says this field
16                         is required. If it is not set in the constructor
17                         call, an error string is returned.
18
19         default         The value for this is the default for this
20                         field. It is used if this field is not set in
21                         the constructor.
22
23         class           The value for this is a Stem class (Perl
24                         package) name. It means the value of this
25                         parameter will be parsed as the arguments to the
26                         constructor ('new' for now) of that class. The
27                         object returned is saved as the value of this
28                         field. If the called constructor returns an
29                         error string, it is returned.
30
31         class_args      The value of this is an anonymous list
32                         of attribute/value pairs for this class
33                         field. They are passed after the caller's
34                         arguments and so will override any duplicate
35                         passed in parameters.
36
37         callback        The value of this is a code reference which is
38                         called to do custom construction of this
39                         field. The code ref is called with the new
40                         object, the field name and the anonymous
41                         reference which has the field's passed in
42                         values.
43
44         type            The value for this attribute is the type of the
45                         field. Currently unsupported, it is meant for
46                         stronger type checking of parameters such as
47                         booleans. This will be supported soon.
48
49         env             The value for this attribute is a name of a Stem
50                         environment variable. If this name is found in
51                         %Stem::Vars::Env then the value in that
52                         hash is used as the value for this
53                         attribute. This overrides any value passed in
54                         the the constructor or a default option.
55                         NOTE: Stem environment variables can be set from
56                         many places including the command line, the
57                         shell environment, command messages and the terminal.
58
59 Here is a typical constructor from the Stem::Log class. It has 3 fields
60 of which the first is required the other two have defaults. The
61 beginning of the constructor sub is shown below and that same two lines
62 of code is used in almost every class constructor.
63
64
65 my $field_info = [
66
67         {
68                 'name'          =>      'log',
69                 'required'      =>      1,
70         },
71         {
72                 'name'          =>      'level',
73                 'default'       =>      'info',
74         },
75         {
76                 'name'          =>      'text',
77                 'default'       =>      '',
78         },
79
80 ] ;
81
82 sub new
83
84         my $self = Stem::Class::parse_args( $field_info, @_ ) ;
85         return $self unless ref $self ;
86
87
88 Object Creation Error Handling
89
90 Stem cells and objects are being created all the time and in many
91 ways. There is a standard way Stem constructor subs return errors. If the
92 object construction works, it returns the object. If there is an error,
93 it returns the error string. The caller must test constructor
94 returns with ref to see if they worked. This makes it easy to pass back
95 error messages to higher level objects with this code shown above.
96
97 The first line parses the passed arguments (in @_) with a field
98 description table. The second line tests if an object was created. If it
99 was (ref $self is true), then the constructor continues. Otherwise, the
100 error string is just returned to the caller. So the exact low level
101 error is propagated up the call tree. This is used consistently in all
102 of the constructors so even if you have a class which has a field which
103 is a class (see the 'class' field type above), and it has a parse error,
104 that error will be passed all the way up to the highest level call
105 (typically in the Stem::Config module).
106
107 Stem Cell Configuration
108
109 Stem cells are typically created by the Stem::Conf class. The primary
110 source of configuration data is from a file and that is handled by the
111 load method. Currently config files are legal Perl and are just parsed
112 with string eval. (Don't yell, I know it sucks but it is simple to
113 bootstrap.) The next revision of this module will tighten up the
114 specifications of config files and create a proper parser for it. The
115 parser will probably use Parse::RecDescent (written by our advisor
116 Damian Conway who will probably write the parser for us :). The config
117 syntax will probably be similar to what it is now, but barewords
118 (actually any token without whitespace) will be allowed anywhere. Only
119 value strings with white space will need to be quoted. Config keywords will
120 always be barewords. Fat comma will be supported and [] will demark
121 lists of anything. There won't be any hashes since this is really just a
122 mass of initializations and a list is fine to initialize a hash.
123
124 A Stem cell configuration is comprised of a list of attribute/value
125 pairs. You can also have a list of cell configurations in one file,
126 but each configuration is handled independently. Each configuration
127 entry has only a few options in the usual format of key/value pairs. The
128 first is 'class', which is required and it names the Stem class which
129 will be configured. The next one is 'name' and it is optional but almost
130 always used. It is the name that this cell will be registered as and
131 that is the address that will be used to send messages to this cell. The
132 last major option is 'args' and its value is a list of attribute/value
133 pairs used to initialize the cell.  Which set of configuration options
134 is what controls how a cell is created and/or registered.
135
136 The 'class' option is first processed and if it is not loaded, Stem will
137 load it for you. This can be done remotely which allows for a servlet
138 style of behavior, i.e. a request can come in and be a configuration or
139 converted to one and the required Stem class will be loaded and a cell
140 created. That cell can then be passed a message and respond to it. All
141 of that can occur at runtime on demand.
142
143 If the 'args' option is set, then a constructor of the class is called
144 and it is passed the attribute/value pairs from the list value of
145 'args'. The constructor method is defaulted to 'new' but that can be
146 overridden with the 'method' option. The constructor processes its
147 arguments (most likely using the Stem::Class::parse_args routine
148 described above) and has 3 possible return values. If it returns undef,
149 nothing more is done by the Stem::Conf module for this configuration. If
150 a string is returned, that is assumed to be an error message and it is
151 either printed or returned to the originator of this configuration. Any
152 other configurations in this file (or passed in remote configuration)
153 are skipped. If the retun value is a ref, then it is assumed
154 to be an object and it can be registered with the address in the 'name'
155 option.
156
157 If the 'name' option is set, that will be used to register the cell or
158 class itself. In most of the configuration cases, an object is created
159 by the class constructor with the 'args' option and it is then
160 registered as a cell with that name for its address. If no 'args'
161 option is set, then the class itself is registered under the 'name'
162 value and it is a class level cell. There can only be one class level
163 cell for any class although it could be registered under multiple names
164 (aliases). In addition, the value of the 'name' option is passed along
165 with the 'args' values to the constructor as the attribute 'reg_name'.
166
167 Here are some example classes which are configured in several of those
168 ways:
169
170 The Stem::Hub class needs to be initialized with a registration name
171 but has no other attributes. So its configuration has a 'name' and an
172 'args' option whose value is an empty list (that forces the constructor
173 to be called).
174
175         [
176                 class   =>      'Stem::Hub',
177                 name    =>      'server',
178                 args    =>      [],
179         ]
180
181 The Stem::TTY::Msg class configuration doesn't use the 'name' option and
182 it used an empty 'args' value. So its constructor is called and it
183 returns its single class level object, and that is registered under its
184 class name.
185
186         [
187                 class   =>      'Stem::TTY::Msg',
188                 args    =>      [],
189         ]
190
191
192 The Stem::Demo::Cmd class is a class level cell that just has a 'name'
193 option in its configuration and that is used to register the class
194 itself.
195
196         [
197                 class   =>      'Stem::Demo::Cmd',
198                 name    =>      'cmd',
199         ]
200
201
202 The Stem::Sock::Msg is configured in the most common way, with 'name' and
203 'args' options and values for the arguments.
204
205         [
206                 class   =>      'Stem::Sock::Msg',
207                 name    =>      'C',
208                 args    =>      [
209                         port    => 6668,
210                         server  => 1,
211                         data_msg        => [
212                                 to_cell         => 'sw',
213                                 to_target       => 'c',
214                         ],
215                 ],
216         ]
217
218
219 Normally a single configuration file is loaded by the run_stem program
220 at start up time.  The Stem::Conf module also supports loading a
221 configuration file via a command message or another configuration (which
222 is similar to include files or Perl modules). A configuration which
223 loads a configuration file can evaluate in the current Hub or send it to
224 any Hub in the Stem system. This allows for centralized management of
225 Stem configurations. As an aid to this, the stem_msg program can be used
226 to send a 'load' command message to a Hub.
227