Skip to content

Instantly share code, notes, and snippets.

@mala
Created October 5, 2009 13:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mala/202121 to your computer and use it in GitHub Desktop.
Save mala/202121 to your computer and use it in GitHub Desktop.
package Plack::Middleware::AsyncSupport;
use strict;
use warnings;
use base qw/Plack::Middleware/;
our $USE_CORO = 1;
use Coro;
use Coro::Channel;
use IO::Handle::Util qw(io_from_getline);
sub call {
my $self = shift;
my $env = shift;
my $res = $self->app->($env);
my $body = $res->[2];
if (ref $body eq "CODE" && $USE_CORO) {
my $queue = Coro::Channel->new;
async {
my $closed = 0;
my $cancel = $body->(
sub { warn "write"; $queue->put($_[0]) }, # write cb
sub { warn "close"; $closed = 1; $queue->shutdown; }, # close cb
);
if (!$closed) {
# TODO: event based code, wait close cb, check timeout
}
};
$res->[2] = io_from_getline sub { $queue->get };
} elsif (ref $body eq "CODE") {
# TODO
# $res->[2] = Plack::AsyncResponse->new($env, $body);
}
return $res;
}
1;
__END__
=head1 NAME
Plack::Middleware::AsyncSupport - convert coderef to Stream
=head1 SYNOPSIS
use Plack::Builder;
use Plack::Middleware qw(AsyncSupport);
# your app with coro
# blocking code, run in thread(Coro) or fork
use Coro::Timer qw(sleep);
my $app = sub {
my $body = sub {
my ($writer, $close) = @_;
my $i = 0;
while ($i < 10) {
$writer->(time . "\n");
sleep 1;
$i++;
}
$close->();
};
return [200, [], $body];
};
# TODO: your app with AnyEvent
# non-blocking code, return canceler
my $app = sub {
my $body = sub {
my ($writer, $close) = @_;
my $i = 0;
my $timer; $timer = AE::timer 0, 1, sub {
$writer->(time . "\n");
$i++;
if ($i >= 10) {
$close->();
undef $timer;
}
};
return sub { undef $timer } # canceler & keep $timer
};
return [200, [], $body];
};
builder {
enable Plack::Middleware::OtherMiddleware;
enable Plack::Middleware::AsyncSupport;
$app;
};
=head1 DESCRIPTION
=head1 AUTHOR
mala
=head1 SEE ALSO
L<Plack::Middleware> L<Plack::Builder>
=cut
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment