|
NAMEPOE::Component::IKC::Responder - POE IKC state handlerSYNOPSISuse POE; use POE::Component::IKC::Responder; create_ikc_responder(); ... $kernel->post('IKC', 'post', $to_state, $state); $ikc->publish('my_name', [qw(state1 state2 state3)]); DESCRIPTIONThis module implements POE IKC state handling. The responder handles posting states to foreign kernels and calling states in the local kernel at the request of foreign kernels.There are 2 interfaces to the responder. Either by sending states to the 'IKC' session or the object interface. While the latter is faster, the better behaved, because POE is a cooperative system. STATES/METHODS"spawn"POE::Component::IKC::Responder->spawn(); This function creates the Responder session and object. Normally, POE::Component::IKC::Client or POE::Component::IKC::Server does this for you. But in some applications you want to make sure that the Responder is up and running before then. "post"Sends an state request to a foreign kernel. Returns logical true if the state was sent and logical false if it was unable to send the request to the foreign kernel. This does not mean that the foreign kernel was able to post the state, however. Parameters are as follows :
See the "PROXY SENDER" below. "call"This is identical to "post", except it has a 3rd parameter that describes what state should receive the return value from the foreign kernel.$kernel->post('IKC', 'call', 'poe://Pulse/timeserver/time', '', 'poe:get_time'); or $ikc->call({kernel=>'Pulse', session=>'timeserver', state=>'time'}, '', 'poe://me/get_time'); This asks the foreign kernel 'Pulse' for the time. 'get_time' state in the current session is posted with whatever the foreign state returned. You do not have to publish callback messages, because they are temporarily published. How temporary? They can be posted from a remote kernel ONCE only. This, of course, is a problem because someone else could get in a post before the callback. Such is life.
$kernel->call('IKC', 'post', {kernel=>'e-comm', session=>'CC', state=>'check'}, {CC=>$cc, expiry=>$expiry}, folder=>$holder}, 'is_valid'); # or $ikc->call('poe://e-comm/CC/check', {CC=>$cc, expiry=>$expiry}, folder=>$holder}, 'poe://me/is_valid'); This asks the e-comm server to check if a credit card number is "well formed". Yes, this would probably be massive overkill. The "rsvp" state does not need to be published. IKC keeps track of the rsvp state and will allow the foreign kernel to post to it. See the "PROXY SENDER" below. "default"Sets the default foreign kernel. You must be connected to the foreign kernel first.Unique parameter is the name of the foreign kernel kernel. Returns logical true on success. "register"Registers foreign kernel names with the responder. This is done during the negociation phase of IKC and is normaly handled by "IKC::Channel". Will define the default kernel if no previous default kernel exists.First parameter is either a single kernel name. Second optional parameter is an array ref of kernel aliases to be registered. "unregister"Unregisters one or more foreign kernel names with the responder. This is done when the foreign kernel disconnects by POE::Component::IKC::Channel. If this is the default kernel, there is no more default kernel.First parameter is either a single kernel name or a kernel alias. Second optional parameter is an array ref of kernel aliases to be unregistered. This second parameter is a tad silly, because if you unregister a remote kernel, it goes without saying that all it's aliases get unregistered also. "register_local"Registers new aliases for local kernel with the responder. This is done internally by POE::Component::IKC::Server and POE::Component::IKC::Client. Will NOT define the default kernel.First and only parameter is an array ref of kernel aliases to be registered. "publish"Tell IKC that some states in the current session are available for use by foreign sessions.
"retract"Tell IKC that some states should no longer be available for use by foreign sessions. You do not have to retract all published states.
"published"$list=$kernel->call(IKC=>'published', $session); Returns a list of all the published states. $hash=$kernel->call(IKC=>'published'); Returns a hashref, keyed on session IDs. Values are arrayref of states published by that session.
"subscribe"Subscribe to foreign sessions or states. When you have subscribed to a foreign session, a proxy session is created on the local kernel that will allow you to post to it like any other local session.
"unsubscribe"Reverse of the "subscribe" method. However, it is currently not documented well."ping"Responds with 'PONG'. This is auto-published, so it can be called from remote kernels to see if the local kernel is still around. In fact, I don't see any other use for this.$kernel->post('poe://remote/IKC', 'ping', 'some_state'); $kernel->delay('some_state', 60); # timeout sub some_state { my($pong)=$_[ARG0]; return if $pong; # all is cool # YOW! Remote kernel timed out. RUN AROUND SCREAMING! } "shutdown"Hopefully causes IKC and all peripheral sessions to dissapear in a puff of smoke. At the very least, any sessions left will be either not related to IKC or barely breathing (that is, only have aliases keeping them from GC). This should allow you to sanely shut down your process."monitor"Allows a session to monitor the state of remote kernels. Currently, a session is informed when a remote kernel is registered, unregistered, subscribed to or unsubscribed from. One should make sure that the IKC alias exists before trying to monitor. Do this by calling POE::Component::IKC::Responder->spawn or in an "on_connect" callback.$kernel->post('IKC', 'monitor', $remote_kernel_id, $states);
Callback statesThe following states can be monitored:
The callback states are called the following parameters :
Most of the time, ARG0 and ARG1 will be the same. Exceptions are if you are monitoring "*" or if you supplied a full IKC event specifier to IKC/monitor rather then just a plain kernel name. Short note about monitoring all kernels with "*"There are 2 reasons circonstances in which you will be monitoring all remote kernels : names known in advance and names unknown in advance.If you know kernel names in advance, you might be better off monitoring a given kernel name. However, you might prefer doing a case-like compare on ARG1 (with regexes, say). This would be useful for clustering, where various redundant kernels could follow a naming convention like [application]-[host], so you could compare "ARG1" with "/^credit-/" to find out if you want to set up specific things for that kernel. Not knowing the name of a kernel in advance, you could be doing some sort of autodiscovery or maybe just monitoring for debuging, logging or book-keeping purposes. You obviously don't want to do autodiscovery for every alias of every kernel, only for the "cannonical name", hence the need for ARG2. Short note the secondYou are more then allowed (in fact, you are encouraged) to use the same callback states when monitoring multiple kernels. In this case, you will find ARG0 useful for telling them apart.$kernel->post('IKC', 'monitor', '*', {register=>'remote_register', unregister=>'remote_unregister', subscribe=>'remote_subscribe', unsubscribe=>'remote_unsubscribe', data=>'magic box'}); Now remote_{register,unregister,subscribe,unsubscribe} is called for any remote kernel. $kernel->post('IKC', 'monitor', 'Pulse', {register=>'pulse_connected'}); "pulse_connected" will be called in current session when you succeed in connecting to a kernel called 'Pulse'. $kernel->post('IKC', 'monitor', '*'); Session is no longer monitoring all kernels, only 'Pulse'. $kernel->post('IKC', 'monitor', 'Pulse', {}); Now we aren't even interested in 'Pulse'; CHANNELSPrevious versions of IKC did not adequately allow you to control a connection. With 0.2400 we added a much needed feature.Each connection to a remote kernel is handled by a channel session. You find out the session's ID by monitoring for "channel" operations. You may close a channel and the corresponding connection to the remote kernel by sending it a "shutdown" event. sub _start { # set up the monitor $poe_kernel->call( IKC => monitor => '*' => { channel => 'channel' } ); } sub channel { my( $self, $rid, $rkernel, $real, $data, $op, $channel ) = @_[ OBJECT, ARG0..$#_ ]; return unless $real; # only care about the real kernel ID if( $op eq 'ready' ) { # new channel is ready $self->{channel}{ $rkernel } = $channel; } elsif( $op eq 'close' ) { # channel is gone delete $self->{channel}{ $rkernel }; } } # this an event posted from your controler logic sub close_channel { my( $self, $rkernel ) = @_[ OBJECT, ARG0 ]; # tell the channel to close $poe_kernel->post( $self->{channel}{ $rkernel } => 'shutdown' ); } ERRORSPrevious versions of IKC did not adequately allow you to monitor for errors on a connection. With 0.2400 we started monitoring errors.There are 2 step during which you can have errors: when opening the connection and during message exchange. These 2 steps are handled diffrently. You use "on_error" in POE::Component::IKC::Client and "on_error" in POE::Component::IKC::Server to receive errors while a connection is being opened. Note that this includes the initial IKC handshake. sub on_error { my( $op, $errnum, $errstr ) = @_; # Handle this like you would any POE socket error # But remember you can't rely on your session being active } You use "monitor" on error to receive errors during message exchange. ARG3 is the name of the operation. ARG4 is the error message. Current operations are:
Example monitor for error events: sub monitor_error { my( $self, $rid, $kernel, $real, $data, $op, $message ) = @_[ OBJECT, ARG0 ... $#_ ]; if( $op =~ /^channel-/ and $message =~ /\[(\d+)\] (.*)/ ) { return unless $real; my( $errnum, $errstr ) = ( $1, $2 ); if( $op eq 'channel-read' and $errnum == 0 ) { warn "Connection closed"; return; } } warn "Error during $op: $message"; } In particular, you will note we don't do anything when we detect the channel closed. Instead, it is recommended to attempt reconnection in the "unregister" event. EXPORTED FUNCTIONS"create_ikc_responder"DEPRECATED. Please usePOE::Compontent::IKC::Responder->spawn(); PROXY SENDEREvent handlers invoked via IKC will have a proxy SENDER session. You may use it to post back to the remote session.$poe_kernel->post( $_[SENDER], 'response', @args ); Normally this proxy session is available during the invocation of the event handler. You may claim it for longer by setting an external reference: $heap->{remote} = $_[SENDER]->ID; $poe_kernel->refcount_increment( $heap->{remote}, 'MINE' ); POE::Component::IKC will detect this and create a new proxy session for future calls. It will then be UP TO YOU to free the session: $poe_kernel->refcount_decrement( $heap->{remote}, 'MINE' ); Note that you will have to publish any events that will be posted back. BUGSSending session references and coderefs to a foreign kernel is a bad idea. At some point it would be desirable to recurse through the paramerters and and turn any session references into state specifiers.The "rsvp" state in call is a bit problematic. IKC allows it to be posted to once, but doesn't check to see if the foreign kernel is the right one. "retract" does not currently tell foreign kernels that have subscribed to a session/state about the retraction. "call()"ing a state in a proxied foreign session doesn't work, for obvious reasons. AUTHORPhilip Gwyn, <perl-ikc at pied.nu>COPYRIGHT AND LICENSECopyright 1999-2014 by Philip Gwyn. All rights reserved.This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See <http://www.perl.com/language/misc/Artistic.html> SEE ALSOPOE, POE::Component::IKC::Server, POE::Component::IKC::Client, POE::Component::IKC::ClientLite, POE::Component::IKC::Channel, POE::Component::IKC::Proxy, POE::Component::IKC::Freezer, POE::Component::IKC::Specifier.
Visit the GSP FreeBSD Man Page Interface. |