AxKit2
view release on metacpan or search on metacpan
lib/AxKit2/Plugin.pm view on Meta::CPAN
=item * Anything Else - ... TBD.
=back
=head2 disconnect
TBD
=head2 error
Params: ERROR
Called whenever a hook C<die()>s or returns C<SERVER_ERROR>.
Return Value:
=over 4
=item * C<DECLINED> - Use default error handler
=item * C<OK/DONE> - Error was sent to browser. Ignore.
=item * Anything Else - Send a different error to the browser.
=back
=head1 CONTINUATIONS
AxKit2 is entirely single threaded, and so it is important not to do things that
take significant runtime away from the main event loop. A simple example of this
might be looking up a request on a remote web server - while the AxKit process
waits for the response it is important to allow AxKit to continue on processing
other requests.
In order to achieve this AxKit2 uses a simplified version of a technique known
in computer science terms as a I<continuation>.
In simple english, this is a way to suspend execution of one request and
I<continue> it at an arbitrary later time.
AxKit2 has a form of continuations based on the core event loop. Some hooks can
suspend execution by returning C<CONTINUATION>, and have execution of the
request continue when some event has occured.
A typical usage of this is when you need to perform an action that may take some
time. An example of this is disk I/O - typical I/O in the common POSIX
read/write style APIs occurs in a blocking manner - when you ask for a C<read()>
the disk seeks to the position you need it to go to when it can do so and the
read is performed as soon as possible before the API call returns. This may take
very little CPU time because the OS has to wait until the disk head is in the
correct position to perform the actions requested. But it does take "clock" time
which can be put to better use responding to other requests.
In asynchronous I/O the action is requested and a callback is provided to
be called when the action has occured. This allows the event loop to continue
processing other requests while we are waiting for the disk.
This is better explained with a simple example. For this example we'll take the
C<stat()> system call in an attempt to find out if the filename we are
requesting is a directory or not. In perl we would normally perform this with
the following code:
sub hook_response {
my $self = shift;
my $filename = $self->client->headers_in->filename;
if (-d $filename) {
....
}
$self->do_something_else();
return OK;
}
However with AIO and continuations we can re-write that as:
sub hook_response1 {
my $self = shift;
my $client = $self->shift;
my $filename = $self->client->headers_in->filename;
IO::AIO::aio_stat $filename, sub {
if (-d _) {
...
}
$self->do_something_else();
$client->finish_continuation;
};
return CONTINUATION;
}
sub hook_response2 {
return DECLINED;
}
A first read will prove one thing - AIO and continuations are a I<lot> harder
than regular procedural code. However often the performance benefits are worth
it.
In general if you need to use continuations then consult the plugins in the
F<aio/> directory, and send emails to the mailing list, as they are generally
a big source of hard to locate bugs.
=head1 SEE ALSO
L<AxKit2::Connection>
L<AxKit2::HTTPHeaders>
L<AxKit2::Constants>
L<AxKit2::Processor>
=cut
( run in 1.698 second using v1.01-cache-2.11-cpan-39bf76dae61 )