1POE::Component::SyndicaUtsoerr(3C)ontributed Perl DocumePnOtEa:t:iCoonmponent::Syndicator(3)
2
3
4
6 POE::Component::Syndicator - A POE component base class which
7 implements the Observer pattern
8
10 package POE::Component::IRC;
11
12 use strict;
13 use warnings;
14 use POE;
15 use base 'POE::Component::Syndicator';
16
17 # our constructor
18 sub spawn {
19 my ($package, %args) = @_;
20
21 # process arguments...
22
23 my $self = bless \%args, $package;
24
25 # set up our plugin system and POE session
26 $self->_syndicator_init(
27 prefix => 'irc_',
28 reg_prefix => 'PCI_',
29 types => [SERVER => 'S', USER => 'U'],
30 object_states => [qw(
31 syndicator_started
32 shutdown
33 )],
34 );
35
36 return $self;
37 }
38
39 sub syndicator_started {
40 my ($kernel, $self) = @_[KERNEL, OBJECT];
41
42 # connect to a server, etc...
43 }
44
45 # plugin handler for SERVER event 'hlagh'
46 sub S_hlagh {
47 # ...
48 }
49
50 sub shutdown {
51 my ($kernel, $self) = @_[KERNEL, OBJECT];
52
53 # disconnect from a server, etc...
54
55 # shut down the syndicator
56 $self->_syndicator_destroy();
57 }
58
60 POE::Component::Syndicator is a base class for POE components which
61 need to handle a persistent resource (e.g. a connection to an IRC
62 server) for one or more sessions in an extendable way.
63
64 This module (as well as Object::Pluggable, which this module inherits
65 from) was born out of POE::Component::IRC, the guts of which quickly
66 spread to other POE components. Now they can all inherit from this
67 module instead.
68
69 The component provides an event queue, which can be managed with the
70 methods documented below. It handles delivery of events to the object
71 itself, all interested plugins, and all interested sessions.
72
73 Component lifetime
74 You start by calling "_syndicator_init", which will create a POE
75 session with your object as its heap, and a few event handlers
76 installed. The events described in "Local events" delimit the start and
77 end of the session's lifetime. In between those, interested plugins and
78 sessions will receive various events, usually starting with
79 "syndicator_registered". In this phase, your subclass and plugins can
80 call the methods and send the events documented below. When the
81 component has been shut down, sessions (but not plugins) will receive a
82 "syndicator_shutdown" event. After this, the component will become
83 unusable.
84
85 A note on events
86 In this document, an event (unless explicitly referred to as a POE
87 event) is defined as a message originating from
88 POE::Component::Syndicator, delivered to plugins (and the subclass) via
89 plugin methods and to registered sessions as POE events.
90
91 Interested sessions are considered consumers only, so they always
92 receive copies of event arguments, whereas interested plugins and
93 subclasses receive scalar references to them. This allows them to
94 alter, add, or remove event arguments before sessions (or even other
95 plugins) receive them. For more information about plugins, see
96 Object::Pluggable's documentation. A subclass does not have to register
97 for plugin events.
98
99 Two event types are supported: SERVER and USER, though their names can
100 be overriden (see "_syndicator_init").
101
102 SERVER events
103
104 These represent data received from the network or some other outside
105 resource (usually a server, hence the default name).
106
107 SERVER events are generated by the "send_event*" methods. These events
108 are delivered to the subclass and plugins (method "S_foo") and
109 interested sessions (event "syndicator_foo").
110
111 USER events
112
113 These represent commands about to be sent to a server or some other
114 resource.
115
116 USER events are generated by "send_user_event". In addition, all POE
117 events sent to this component's session (e.g. with "yield") which do
118 not have a handler will generate corresponding USER events. USER events
119 are considered more private, so they are only delivered to the subclass
120 and plugins, not to sessions.
121
123 The following methods should only be called by a subclass.
124
125 "_syndicator_init"
126 You should call this in your constructor. It initializes
127 Object::Pluggable, creates the Syndicator's POE session, and calls the
128 "syndicator_started" POE events. It takes the following arguments:
129
130 'prefix', a prefix for all your event names, when sent to interested
131 sessions. If you don't supply this, Object::Pluggable's default
132 ('pluggable') will be used.
133
134 'reg_prefix', the prefix for the "register()"/"unregister()" plugin
135 methods If you don't supply this, Object::Pluggable's default
136 ('plugin_') will be used.
137
138 'debug', a boolean, if true, will cause a warning to be printed every
139 time a plugin event handler raises an exception.
140
141 'types', a 2-element arrayref of the types of events that your
142 component will support, or a 4-element (2 pairs) arrayref where the
143 event types are keys and their abbrevations (used as plugin event
144 method prefixes) are values (see "A note on events" and
145 Object::Pluggable for more information). The two event types are
146 fundamentally different, so make sure you supply them in the right
147 order. If you don't provide this argument, "[ SERVER => 'S', USER =>
148 'U' ]" will be used.
149
150 'register_signal', the name of the register signal (see "SIGNALS").
151 Defaults to 'SYNDICATOR_REGISTER'.
152
153 'shutdown_signal', the name of the shutdown signal (see "SIGNALS").
154 Defaults to 'SYNDICATOR_SHUTDOWN'.
155
156 'object_states' an arrayref of additional object states to add to the
157 POE session. Same as the 'object_states' argument to POE::Session's
158 "create" method. You'll want to add a handler for at least the
159 "syndicator_started" event.
160
161 'options', a hash of options for POE::Session's constructor.
162
163 If you call "_syndicator_init" from inside another POE session, the
164 component will automatically register that session as wanting all
165 events. That session will first receive a "syndicator_registered"
166 event.
167
168 "_syndicator_destroy"
169 Call this method when you want Syndicator to clean up (delete all
170 plugins, etc) and make sure it won't keep the POE session alive after
171 all remaining events have been processed. A "syndicator_shutdown" event
172 (or similar, depending on the prefix you chose) will be generated. Any
173 argument passed to "_syndicator_destroy" will be passed along with that
174 event.
175
176 Note: this method will clear all alarms for the POE session.
177
179 "session_id"
180 Returns the component's POE session id.
181
182 "session_alias"
183 Returns the component's POE session alias.
184
185 "yield"
186 This method provides an alternative, object-based means of posting
187 events to the component. First argument is the event to post, following
188 arguments are sent as arguments to the resultant post.
189
190 "call"
191 This method provides an alternative, object-based means of calling
192 events to the component. First argument is the event to call, following
193 arguments are sent as arguments to the resultant call.
194
195 "send_event"
196 Adds a new SERVER event onto the end of the queue. The event will be
197 processed after other pending events, if any. First argument is an
198 event name, the rest are the event arguments.
199
200 $component->send_event('irc_public, 'foo!bar@baz.com', ['#mychan'], 'message');
201
202 "send_event_next"
203 Adds a new SERVER event to the start of the queue. The event will be
204 the next one to be processed. First argument is an event name, the rest
205 are the event arguments.
206
207 "send_event_now"
208 Sends a new SERVER event immediately. Execution of the current POE
209 event will be suspended (i.e. this call will block) until the new event
210 has been processed by the component class and all plugins. First
211 argument is an event name, the rest are the event arguments.
212
213 "send_user_event"
214 Sends a new USER event immediately. You should call this before every
215 command you send to your remote server/resource. Only the subclass and
216 plugins will see this event. Takes two arguments, an event name and an
217 arrayref of arguments. Returns one of the "EAT" constants listed in
218 Object::Pluggable::Constants. After this method returns, the arrayref's
219 contents may have been modified by the subclass or plugins.
220
221 $component->send_user_event('PRIVMSG', '#mychan', 'message');
222
223 "delay"
224 This method provides a way of posting delayed events to the component.
225 The first argument is an arrayref consisting of the delayed command to
226 post and any command arguments. The second argument is the time in
227 seconds that one wishes to delay the command being posted.
228
229 my $alarm_id = $component->delay(['mode', $channel, '+o', $dude], 60);
230
231 "delay_remove"
232 This method removes a previously scheduled delayed event from the
233 component. Takes one argument, the "alarm_id" that was returned by a
234 "delay" method call. Returns an arrayref of arguments to the event that
235 was originally requested to be delayed.
236
237 my $arrayref = $component->delay_remove($alarm_id);
238
240 Local events
241 The component will send the following POE events to its session.
242
243 "syndicator_started"
244
245 Called after the session has been started (like "_start" in
246 POE::Kernel. This is where you should do your POE-related setup work
247 such as adding new event handlers to the session.
248
249 "syndicator_stopped"
250
251 Called right before the session is about to die (like "_stop" in
252 POE::Kernel).
253
254 Input events
255 Other POE sessions can send the following POE events to the
256 Syndicator's session.
257
258 "register"
259
260 Takes any amount of arguments: a list of event names that your session
261 wants to listen for, minus the prefix (specified in "_syndicator_init"
262 in "syndicator_init").
263
264 $kernel->post('my syndicator', 'register', qw(join part quit kick));
265
266 Registering for the special event 'all' will cause it to send all
267 events to your session. Calling it with no event names is equivalent to
268 calling it with 'all' as an argumente.
269
270 Registering will generate a "syndicator_registered" event that your
271 session can trap.
272
273 Registering with multiple component sessions can be tricky, especially
274 if one wants to marry up sessions/objects, etc. Check the SIGNALS
275 section for an alternative method of registering with multiple
276 components.
277
278 "unregister"
279
280 Takes any amount of arguments: a list of event names which you don't
281 want to receive. If you've previously done a "register" for a
282 particular event which you no longer care about, this event will tell
283 the component to stop sending them to you. (If you haven't, it just
284 ignores you. No big deal.) Calling it with no event names is equivalent
285 to calling it with 'all' as an argument.
286
287 If you have registered for the special event 'all', attempting to
288 unregister individual events will not work. This is a 'feature'.
289
290 "shutdown"
291
292 By default, POE::Component::Syndicator sessions never go away. You can
293 send its session a "shutdown" event manually to make it delete itself.
294 Terminating multiple Syndicators can be tricky. Check the "SIGNALS"
295 section for a method of doing that.
296
297 "_default"
298
299 Any POE events sent to the Syndicator's session which do not have a
300 handler will go to the Syndicator's "_default" handler, will generate
301 "USER events" of the same name. If you install your own "_default"
302 handler, make sure you do the same thing before you handle an event:
303
304 use Object::Pluggable::Constants 'PLUGIN_EAT_ALL';
305
306 $poe_kernel->state('_default', $self, '__default');
307
308 sub __default {
309 my ($self, $event, $args) = @_[OBJECT, ARG0, ARG1];
310
311 # do nothing if a plugin eats the event
312 return if $self->send_user_event($event, [@$args]) == PLUGIN_EAT_ALL;
313
314 # handle the event
315 # ...
316 }
317
318 Note that the handler for the "_default" event must be named something
319 other than '_default', because that name is reserved for the plugin-
320 type default handler (see the Object::Pluggable docs).
321
322 Output events
323 The Syndicator will send the following events at various times. The
324 'syndicator_' prefix in these event names can be customized with a
325 'prefix' argument to "_syndicator_init" in "_syndicator_init".
326
327 "syndicator_registered"
328
329 Sent once to the requesting session on registration (see "register").
330 "ARG0" is a reference to the component's object.
331
332 "syndicator_shutdown"
333
334 Sent to all interested sessions when the component has been shut down.
335 See "_syndicator_destroy".
336
337 "syndicator_delay_set"
338
339 Sent to the subclass, plugins, and all interested sessions on a
340 successful addition of a delayed event using the "delay" method. "ARG0"
341 will be the alarm_id which can be used later with "delay_remove".
342 Subsequent parameters are the arguments that were passed to "delay".
343
344 "syndicator_delay_removed"
345
346 Sent to the subclass, plugins, and all interested sessions when a
347 delayed event is successfully removed. "ARG0" will be the alarm_id that
348 was removed. Subsequent parameters are the arguments that were passed
349 to "delay".
350
351 All other events
352
353 All other events sent by the Syndicator are USER events (generated with
354 "send_user_event") and SERVER events (generated with "send_event*")
355 which will be delivered normally. Your subclass and plugins are
356 responsible for generating them.
357
359 The component will handle a number of custom signals that you may send
360 using POE::Kernel's "signal" method. They allow any session to
361 communicate with every instance of the component in certain ways
362 without having references to their objects or knowing about their
363 sessions. The names of these signals can be customized with
364 "_syndicator_init".
365
366 "SYNDICATOR_REGISTER"
367 Registers for an event with the component. See "register".
368
369 "SYNDICATOR_SHUTDOWN"
370 Causes a 'shutdown' event to be sent to your session. Any arguments to
371 the signal will be passed along to the event. That's where you should
372 clean up and call "_syndicator_destroy".
373
375 Hinrik Örn Sigurðsson, hinrik.sig@gmail.com, Chris "BinGOs" Williams
376 chris@bingosnet.co.uk, Apocalypse apocal@cpan.org, and probably others.
377
379 Copyright 2011 Hinrik Örn Sigurðsson
380
381 This program is free software, you can redistribute it and/or modify it
382 under the same terms as Perl itself.
383
384
385
386perl v5.28.0 2011-06-20 POE::Component::Syndicator(3)