NAME
POE::Request - a common message class for POE::Stage
SYNOPSIS
# Note, this is not a complete program.
# See the distribution's examples directory.
my $request :Req = POE::Request->new(
method => "method_name", # invoke this method
stage => $self->{stage_object}, # of this stage
on_one => "do_one", # map a "one" response to method
args => {
param_1 => 123, # with this parameter
param_2 => "abc", # and this one
}
);
# Handle a "one" response.
sub do_one {
my ($self, $args) = @_;
print "$args->{param_1}\n"; # 123
print "$args->{param_2}\n"; # abc
...;
req()->return( type => "one", moo => "retval" );
}
# Handle one's return value.
sub do_one {
my ($self, $args) = @_;
print "$args->{moo}\n"; # retval
}
DESCRIPTION
POE::Request objects are the messages passed between POE::Stage objects. They include a destination (stage and method), values to pass to the destination method, mappings between return message types and the source methods to handle them, and possibly other parameters.
POE::Request includes methods that can be used to send responses to an initiating request. It internally uses POE::Request subclasses to encapsulate the resulting messages.
Requests may also be considered the start of two-way dialogues. The emit() method may be used by an invoked stage to send back an interim response, and then the caller may use recall() on the interim response to send an associated request back to the invoked stage.
Each POE::Request object can be considered as a continuation. Variables may be associated with either the caller's or invocant stage's side of a request. Values associated with one side are not visible to the other side, even if they share the same variable name. The associated variables and their values are always in scope when that side of the request is active. Variables associated with a request are destroyed when the request is canceled or completed.
For example, a sub-request is created within the context of the current request.
sub some_request_sender {
my $foo :Req = POE::Request->new(...);
}
Whenever the same request is active, my $foo :Req;
imports the field (with its current value) in the current scope.
Furthermore, fields may be associated with a particular request. These will be available again in response handlers using the special ":Rsp" attribute:
sub some_request_sender {
my $foo :Req = POE::Request->new(...);
my $foo_field :Req($foo) = "a sample value";
}
sub some_response_handler {
my $foo_field :Rsp;
print "$foo_field\n"; # "a sample value"
}
PUBLIC METHODS
Request methods are called directly on the objects themselves.
new PARAM => VALUE, PARAM => VALUE, ...
Create a new POE::Request object. The request will automatically be sent to its destination. Factors on the local or remote process, or pertaining to the network between them, may prevent the request from being delivered immediately.
POE::Request->new() requires at least two parameters. "stage" contains the POE::Stage object that will receive the request. "method" is the method to call when the remote stage handles the request. The stage may merely be a local proxy for a remote object, but this feature has yet to be defined.
Parameters for the message's destination can be supplied in the optional "args" parameter. These parameters will be passed untouched to the message's destination's $args parameter.
POE::Request->new() returns an object which must be saved. Destroying a request object will cancel the request and automatically free all data and resources associated with it, including sub-stages and sub-requests. This is ensured by storing sub-stages and sub-requests within the context of higher-level requests.
Instances of POE::Request subclasses, such as those created by $request->return(), do not need to be saved. They are ephemeral responses and re-requests, and their lifespans do not control the lifetime duration of the original request.
init HASHREF
The init() method receives the request's constructor $args before they are processed and stored in the request. Its timing gives it the ability to modify members of $args, add new ones, or remove old ones.
Custom POE::Request subclasses may use init() to verify that parameters are correct. Currently init() must throw an exeception with die() to signal some form of failure.
return type => RETURN_TYPE, RETURN_MEMBER => RETURN_VALUE, ...
Cancels the current POE::Request object, invalidating it for future operations, and internally creates a return message via POE::Request::Return. This return message is initialized with pairs of RETURN_MEMBER => RETURN_VALUE parameters. It is automatically (if not immediately) sent back to the POE::Stage that created the original request.
Please see POE::Request::Return for details about return messages.
If the type of message is not selected, it defaults to "return".
emit type => EMIT_TYPE, EMIT_MEMBER => EMIT_VALUE, ...
Creates a POE::Request::Emit object initialized with the pairs of EMIT_MEMBER => EMIT_VALUE parameters. The emitted response will be automatically sent back to the creator of the request being invoked.
Unlike return(), emit() does not cancel the current request, and emitted messages can be replied. It is designed to send back an interim response but not end the request.
If the type of message is not selected, it defaults to "emit".
cancel
Explicitly cancel a request. Mainly used by the invoked stage, not the caller. Normally destroying the request object is sufficient, but this may only be done by the caller. The request's receiver can call cancel() however.
As mentioned earlier, canceling a request frees up the data associated with that request. Cancellation and destruction cascade through the data associated with a request and any sub-stages and sub-requests. This efficiently and automatically releases all resources associated with the entire request tree rooted with the canceled request.
A canceled request cannot generate a response. If you are tempted to follow emit() with a cancel(), then use return() instead. The return() method is essentially an emit() and cancel() together.
DESIGN GOALS
Requests are designed to encapsulate messages passed between stages, so you don't have to. It's our hope that providing a standard, effective message passing system will maximize interoperability between POE stages.
Requests may be subclassed.
At some point in the future, request classes may be used as message types rather than <type =
$type>> parameters. More formal POE::Stage interfaces may take advantage of explicit message typing in the future.
BUGS
See http://thirdlobe.com/projects/poe-stage/report/1 for known issues. See http://thirdlobe.com/projects/poe-stage/newticket to report one.
:Req
and :Rsp
must be discussed in greater detail, perhaps in one or more tutorials.
POE::Stage is too young for production use. For example, its syntax is still changing. You probably know what you don't like, or what you need that isn't included, so consider fixing or adding that. It'll bring POE::Stage that much closer to a usable release.
SEE ALSO
POE::Request has subclasses that are used internally. While they share the same interface as POE::Request, all its methods are not appropriate in all its subclasses.
Please see POE::Request::Upward for a discussion of response events, and how they are mapped to method calls by the requesting stage. POE::Request::Return and POE::Request::Emit are specific kinds of upward-facing response messages.
POE::Request::Return, POE::Request::Recall, POE::Request::Emit, and POE::Request::Upward.
AUTHORS
Rocco Caputo <rcaputo@cpan.org>.
LICENSE
POE::Request is Copyright 2005-2006 by Rocco Caputo. All rights are reserved. You may use, modify, and/or distribute this module under the same terms as Perl itself.