diff --git a/eg/demo.pl b/eg/demo.pl index 1402765..8693ee7 100755 --- a/eg/demo.pl +++ b/eg/demo.pl @@ -171,9 +171,8 @@ package main; use Plack::Middleware::Static; $app = Plack::Middleware::Static->wrap($app, path => qr/^\/static/, root => dirname(__FILE__)); -# TODO should this be in Server -use Plack::Middleware::Writer; -$app = Plack::Middleware::Writer->wrap($app); +use Tatsumaki::Middleware::Blocking; +$app = Tatsumaki::Middleware::Blocking->wrap($app); # TODO this should be an external services module use Try::Tiny; diff --git a/lib/Tatsumaki/Handler.pm b/lib/Tatsumaki/Handler.pm index 68374a4..e8de2bd 100644 --- a/lib/Tatsumaki/Handler.pm +++ b/lib/Tatsumaki/Handler.pm @@ -85,11 +85,9 @@ sub run { } if ($self->is_asynchronous) { - unless ($self->request->env->{'psgi.streaming'}) { - Tatsumaki::Error::HTTP->throw(500, "asynchronous handlers need PSGI servers with psgi.streaming"); - } my $cv = AE::cv; $self->condvar($cv); + $self->request->env->{'tatsumaki.block'} = sub { $cv->recv }; return sub { my $start_response = shift; $cv->cb(sub { @@ -97,10 +95,6 @@ sub run { $self->writer($w) if $w; }); $self->$method(@{$self->args}); - unless ($self->request->env->{'psgi.nonblocking'}) { - $self->log("psgi.nonblocking is off: running " . ref($self) . " in a blocking mode\n"); - $cv->recv; - } }; } else { $self->$method(@{$self->args}); diff --git a/lib/Tatsumaki/Middleware/Blocking.pm b/lib/Tatsumaki/Middleware/Blocking.pm new file mode 100644 index 0000000..e73525a --- /dev/null +++ b/lib/Tatsumaki/Middleware/Blocking.pm @@ -0,0 +1,30 @@ +package Tatsumaki::Middleware::Blocking; +use strict; +use base qw(Plack::Middleware); +use Carp (); +use Plack::Util; + +# Run asnynchronous Tatsumaki app in a blocking mode. See also Middleware::Writer +sub call { + my($self, $env) = @_; + + my $caller_supports_streaming = $env->{'psgi.streaming'}; + $env->{'psgi.streaming'} = Plack::Util::TRUE; + + my $res = $self->app->($env); + return $res if $caller_supports_streaming; + + if (ref $res eq 'CODE') { + $env->{'psgi.errors'}->print("psgi.nonblocking is off: running $env->{PATH_INFO} in a blocking mode\n"); + $res->(sub { $res = shift }); + $env->{'tatsumaki.block'}->(); + } + + unless (defined $res->[2]) { + Carp::croak("stream_write is not supported on this server"); + } + + return $res; +} + +1;