]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/GitHTTPBackend.pm
git-http-backend: simplify dumb serving
[public-inbox.git] / lib / PublicInbox / GitHTTPBackend.pm
index b58cc30fc7b96ec5c80b86cb839193dfb16eb15d..97d96d526121752060ff3274dbcdfee57cfebc31 100644 (file)
@@ -11,14 +11,6 @@ use IO::File;
 use PublicInbox::Spawn qw(spawn);
 use HTTP::Date qw(time2str);
 
-# TODO: make configurable, but keep in mind it's better to have
-# multiple -httpd worker processes which are already scaled to
-# the proper number of CPUs and memory.  git-pack-objects(1) may
-# also use threads and bust memory limits, too, so I recommend
-# limiting threads to 1 (via `pack.threads` knob in git) for serving.
-my $LIMIT = 1;
-my $nr_running = 0;
-
 # n.b. serving "description" and "cloneurl" should be innocuous enough to
 # not cause problems.  serving "config" might...
 my @text = qw[HEAD info/refs
@@ -54,7 +46,6 @@ sub r ($) {
 
 sub serve {
        my ($cgi, $git, $path) = @_;
-       return serve_dumb($cgi, $git, $path) if $nr_running >= $LIMIT;
 
        my $service = $cgi->param('service') || '';
        if ($service =~ /\Agit-\w+-pack\z/ || $path =~ /\Agit-\w+-pack\z/) {
@@ -101,43 +92,9 @@ sub serve_dumb {
        # TODO: If-Modified-Since and Last-Modified?
        open my $in, '<', $f or return r(404);
        my $len = $size;
-       my $n = 65536; # try to negotiate a big TCP window, first
-       my ($next, $fh);
-       my $cb = sub {
-               $n = $len if $len < $n;
-               my $r = sysread($in, my $buf, $n);
-               if (!defined $r) {
-                       err($env, "$f read error: $!");
-                       drop_client($env);
-               } elsif ($r <= 0) {
-                       err($env, "$f EOF with $len bytes left");
-                       drop_client($env);
-               } else {
-                       $len -= $r;
-                       $fh->write($buf);
-                       if ($len == 0) {
-                               $fh->close;
-                       } elsif ($next) {
-                               # avoid recursion in Danga::Socket::write
-                               unless ($nextq) {
-                                       $nextq = [];
-                                       Danga::Socket->AddTimer(0, *do_next);
-                               }
-                               # avoid buffering too much in case we have
-                               # slow clients:
-                               $n = 8192;
-                               push @$nextq, $next;
-                               return;
-                       }
-               }
-               # all done, cleanup references:
-               $fh = $next = undef;
-       };
-
        my $code = 200;
        push @h, 'Content-Type', $type;
-       my $range = $env->{HTTP_RANGE};
-       if (defined $range && $range =~ /\bbytes=(\d*)-(\d*)\z/) {
+       if (($env->{HTTP_RANGE} || '') =~ /\bbytes=(\d*)-(\d*)\z/) {
                ($code, $len) = prepare_range($cgi, $in, \@h, $1, $2, $size);
                if ($code == 416) {
                        push @h, 'Content-Range', "bytes */$size";
@@ -145,18 +102,24 @@ sub serve_dumb {
                }
        }
        push @h, 'Content-Length', $len;
-
-       sub {
-               my ($res) = @_; # Plack callback
-               $fh = $res->([ $code, \@h ]);
-               if (defined $env->{'pi-httpd.async'}) {
-                       my $pi_http = $env->{'psgix.io'};
-                       $next = sub { $pi_http->write($cb) };
-                       $cb->(); # start it off!
-               } else {
-                       $cb->() while $fh;
-               }
-       }
+       my $n = 65536;
+       [ $code, \@h, Plack::Util::inline_object(close => sub { close $in },
+               getline => sub {
+                       return if $len == 0;
+                       $n = $len if $len < $n;
+                       my $r = sysread($in, my $buf, $n);
+                       if (!defined $r) {
+                               err($env, "$f read error: $!");
+                       } elsif ($r <= 0) {
+                               err($env, "$f EOF with $len bytes left");
+                       } else {
+                               $len -= $r;
+                               $n = 8192;
+                               return $buf;
+                       }
+                       drop_client($env);
+                       return;
+               })]
 }
 
 sub prepare_range {
@@ -243,7 +206,6 @@ sub serve_smart {
        $wpipe = $in = undef;
        $buf = '';
        my ($vin, $fh, $res);
-       $nr_running++;
 
        # Danga::Socket users, we queue up the read_enable callback to
        # fire after pending writes are complete:
@@ -264,7 +226,6 @@ sub serve_smart {
                        # PublicInbox::HTTPD::Async::close:
                        $rpipe->close;
                        $rpipe = undef;
-                       $nr_running--;
                }
                if (defined $pid) {
                        my $e = $pid == waitpid($pid, 0) ?