user/dev discussion of public-inbox itself
 help / color / mirror / code / Atom feed
Search results ordered by [date|relevance]  view[summary|nested|Atom feed]
thread overview below | download mbox.gz: |
* [PATCH 0/5] a few more HTTP-async-related simplifications
@ 2016-05-22 20:57  7% Eric Wong
  2016-05-22 20:57  5% ` [PATCH 4/5] http: rework async_pass support Eric Wong
  0 siblings, 1 reply; 2+ results
From: Eric Wong @ 2016-05-22 20:57 UTC (permalink / raw)
  To: meta

Since we'll be doing more expensive processes in repobrowse,
it's prudent to refactor and commonalize some of this code.
Here's a start...

Eric Wong (5):
      t/spawn.t: additional tests for popen_rd
      git-http-backend: remove process limit
      git-http-backend: simplify dumb serving
      http: rework async_pass support
      git-http-backend: switch to async_pass

 lib/PublicInbox/GitHTTPBackend.pm | 251 ++++++++++++++++----------------------
 lib/PublicInbox/HTTP.pm           |  24 +---
 lib/PublicInbox/HTTPD/Async.pm    |  45 ++++---
 t/spawn.t                         |  10 ++
 4 files changed, 143 insertions(+), 187 deletions(-)

^ permalink raw reply	[relevance 7%]

* [PATCH 4/5] http: rework async_pass support
  2016-05-22 20:57  7% [PATCH 0/5] a few more HTTP-async-related simplifications Eric Wong
@ 2016-05-22 20:57  5% ` Eric Wong
  0 siblings, 0 replies; 2+ results
From: Eric Wong @ 2016-05-22 20:57 UTC (permalink / raw)
  To: meta

Unfortunately, the original design did not work because
middleware can wrap the response body and make `async_pass'
invisible to HTTP.pm
---
 lib/PublicInbox/HTTP.pm        | 24 ++++------------------
 lib/PublicInbox/HTTPD/Async.pm | 45 +++++++++++++++++++++++++-----------------
 2 files changed, 31 insertions(+), 38 deletions(-)

diff --git a/lib/PublicInbox/HTTP.pm b/lib/PublicInbox/HTTP.pm
index 4eb1448..480800b 100644
--- a/lib/PublicInbox/HTTP.pm
+++ b/lib/PublicInbox/HTTP.pm
@@ -11,7 +11,7 @@ package PublicInbox::HTTP;
 use strict;
 use warnings;
 use base qw(Danga::Socket);
-use fields qw(httpd env rbuf input_left remote_addr remote_port);
+use fields qw(httpd env rbuf input_left remote_addr remote_port forward);
 use Fcntl qw(:seek);
 use Plack::HTTPParser qw(parse_http_request); # XS or pure Perl
 use HTTP::Status qw(status_message);
@@ -219,24 +219,6 @@ sub response_write {
 		if (ref $body eq 'ARRAY') {
 			$write->($_) foreach @$body;
 			$close->();
-		} elsif ($body->can('async_pass')) { # HTTPD::Async
-			# prevent us from reading the body faster than we
-			# can write to the client
-			my $restart_read = sub { $body->watch_read(1) };
-			$body->async_pass(sub {
-				local $/ = \8192;
-				my $buf = $body->getline;
-				if (defined $buf) {
-					$write->($buf);
-					if ($self->{write_buf_size}) {
-						$body->watch_read(0);
-						$self->write($restart_read);
-					}
-					return; # continue waiting
-				}
-				$body->close;
-				$close->();
-			});
 		} else {
 			my $pull;
 			$pull = sub {
@@ -438,7 +420,9 @@ sub event_err { $_[0]->close }
 
 sub close {
 	my $self = shift;
-	$self->{env} = undef;
+	my $forward = $self->{forward};
+	$forward->close if $forward;
+	$self->{forward} = $self->{env} = undef;
 	$self->SUPER::close(@_);
 }
 
diff --git a/lib/PublicInbox/HTTPD/Async.pm b/lib/PublicInbox/HTTPD/Async.pm
index 8f3a6a0..8efa7a6 100644
--- a/lib/PublicInbox/HTTPD/Async.pm
+++ b/lib/PublicInbox/HTTPD/Async.pm
@@ -21,29 +21,38 @@ sub new {
 	$self;
 }
 
-sub async_pass { $_[0]->{cb} = $_[1] }
-sub event_read { $_[0]->{cb}->() }
-sub event_hup { $_[0]->{cb}->() }
-sub event_err { $_[0]->{cb}->() }
-sub sysread { shift->{sock}->sysread(@_) }
-
-sub getline {
-	my ($self) = @_;
-	die 'getline called without $/ ref' unless ref $/;
-	while (1) {
-		my $ret = $self->read(8192); # Danga::Socket::read
-		return $$ret if defined $ret;
+sub async_pass {
+	my ($self, $io, $fh) = @_;
+	my $restart_read = sub { $self->watch_read(1) };
 
-		return unless $!{EAGAIN} || $!{EINTR};
+	# In case the client HTTP connection ($io) dies, it
+	# will automatically close this ($self) object.
+	$io->{forward} = $self;
+	$self->{cb} = sub {
+		my $r = sysread($self->{sock}, my $buf, 8192);
+		if ($r) {
+			$fh->write($buf);
+			if ($io->{write_buf_size}) {
+				$self->watch_read(0);
+				$io->write($restart_read);
+			}
+			return; # stay in watch_read
+		} elsif (!defined $r) {
+			return if $!{EAGAIN} || $!{EINTR};
+		}
 
-		# in case of spurious wakeup, hopefully we never hit this
-		my $vin = '';
-		vec($vin, $self->{fd}, 1) = 1;
-		my $n;
-		do { $n = select($vin, undef, undef, undef) } until $n;
+		# Done! Error handling will happen in $fh->close
+		$io->{forward} = undef;
+		$self->close;
+		$fh->close;
 	}
 }
 
+sub event_read { $_[0]->{cb}->() }
+sub event_hup { $_[0]->{cb}->() }
+sub event_err { $_[0]->{cb}->() }
+sub sysread { shift->{sock}->sysread(@_) }
+
 sub close {
 	my $self = shift;
 	$self->{cb} = undef;

^ permalink raw reply related	[relevance 5%]

Results 1-2 of 2 | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
2016-05-22 20:57  7% [PATCH 0/5] a few more HTTP-async-related simplifications Eric Wong
2016-05-22 20:57  5% ` [PATCH 4/5] http: rework async_pass support Eric Wong

Code repositories for project(s) associated with this public inbox

	https://80x24.org/public-inbox.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).