about summary refs log tree commit homepage
path: root/lib/PublicInbox
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2016-04-28 01:56:08 +0000
committerEric Wong <e@80x24.org>2016-04-28 02:00:55 +0000
commitd456eb0201550050f8ffa0aa279684976cb942a6 (patch)
treedf1e6e9728054f6439ce90990afc6cb730446157 /lib/PublicInbox
parent6e88eec854e125520b67735df6e4b0de52201383 (diff)
downloadpublic-inbox-d456eb0201550050f8ffa0aa279684976cb942a6.tar.gz
Server admins may not be able to afford to have too many
git-pack-objects processes running at once.  Since PSGI
HTTP servers should already be configured to use multiple
processes for other requests; limit concurrency of smart
backends to one; and fall back to dumb responses if we're
already generating a pack.
Diffstat (limited to 'lib/PublicInbox')
-rw-r--r--lib/PublicInbox/GitHTTPBackend.pm12
1 files changed, 12 insertions, 0 deletions
diff --git a/lib/PublicInbox/GitHTTPBackend.pm b/lib/PublicInbox/GitHTTPBackend.pm
index c44c67d5..a7cac100 100644
--- a/lib/PublicInbox/GitHTTPBackend.pm
+++ b/lib/PublicInbox/GitHTTPBackend.pm
@@ -10,6 +10,14 @@ use Fcntl qw(:seek);
 use IO::File;
 use PublicInbox::Spawn qw(spawn);
 
+# 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
@@ -31,6 +39,8 @@ 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/) {
                 my $ok = serve_smart($cgi, $git, $path);
@@ -174,6 +184,7 @@ sub serve_smart {
         $wpipe = $in = undef;
         $buf = '';
         my ($vin, $fh, $res);
+        $nr_running++;
         my $end = sub {
                 if ($fh) {
                         $fh->close;
@@ -182,6 +193,7 @@ sub serve_smart {
                 if ($rpipe) {
                         $rpipe->close; # _may_ be Danga::Socket::close
                         $rpipe = undef;
+                        $nr_running--;
                 }
                 if (defined $pid && $pid != waitpid($pid, 0)) {
                         $err->print("git http-backend ($git_dir): $?\n");