From fffbc9ec32b78731acd30539f6e3f2778d2d1fb2 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Tue, 22 Jan 2019 02:10:13 +0000 Subject: solver: rewrite to use Qspawn->psgi_qx and pi-httpd.async The psgi_qx routine in the now-abandoned "repobrowse" branch allows us to break down blob-solving at each process execution point. It reuses the Qspawn facility for git-http-backend(1), allowing us to limit parallel subprocesses independently of Perl worker count. This is actually a 2-3% slower a fully-synchronous execution; but it is fair to other clients as it won't monopolize the server for hundreds of milliseconds (or even seconds) at a time. --- lib/PublicInbox/ViewVCS.pm | 51 ++++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 17 deletions(-) (limited to 'lib/PublicInbox/ViewVCS.pm') diff --git a/lib/PublicInbox/ViewVCS.pm b/lib/PublicInbox/ViewVCS.pm index 4a3896d4..fa76086a 100644 --- a/lib/PublicInbox/ViewVCS.pm +++ b/lib/PublicInbox/ViewVCS.pm @@ -27,37 +27,33 @@ my $enc_utf8 = find_encoding('UTF-8'); sub html_page ($$$) { my ($ctx, $code, $strref) = @_; + my $wcb = delete $ctx->{-wcb}; $ctx->{-upfx} = '../../'; # from "/$INBOX/$OID/s/" - PublicInbox::WwwStream->response($ctx, $code, sub { + my $res = PublicInbox::WwwStream->response($ctx, $code, sub { my ($nr, undef) = @_; $nr == 1 ? $$strref : undef; }); + $wcb->($res); } -sub show ($$;$) { - my ($ctx, $oid_b, $fn) = @_; - my $ibx = $ctx->{-inbox}; - my $inboxes = [ $ibx ]; - my $solver = PublicInbox::SolverGit->new($ibx->{-repo_objs}, $inboxes); - my $qp = $ctx->{qp}; - my $hints = {}; - while (my ($from, $to) = each %QP_MAP) { - defined(my $v = $qp->{$from}) or next; - $hints->{$to} = $v; - } - - open my $log, '+>', undef or die "open: $!"; - my $res = $solver->solve($log, $oid_b, $hints); +sub solve_result { + my ($ctx, $res, $log, $hints, $fn) = @_; - seek($log, 0, 0) or die "seek: $!"; + unless (seek($log, 0, 0)) { + $ctx->{env}->{'psgi.errors'}->print("seek(log): $!\n"); + return html_page($ctx, 500, \'seek error'); + } $log = do { local $/; <$log> }; + my $ref = ref($res); + $log .= $res unless $ref; my $l = PublicInbox::Linkify->new; $l->linkify_1($log); $log = '
debug log:

' .
 		$l->linkify_2(ascii_html($log)) . '
'; $res or return html_page($ctx, 404, \$log); + $ref eq 'ARRAY' or return html_page($ctx, 500, \$log); my ($git, $oid, $type, $size, $di) = @$res; if ($size > $max_size) { @@ -78,7 +74,7 @@ sub show ($$;$) { if ($fn) { my $h = [ 'Content-Length', $size, 'Content-Type' ]; push(@$h, ($binary ? 'application/octet-stream' : 'text/plain')); - return [ 200, $h, [ $$blob ]]; + return delete($ctx->{-wcb})->([200, $h, [ $$blob ]]); } my $path = to_filename($di->{path_b} || $hints->{path_b} || 'blob'); @@ -107,4 +103,25 @@ sub show ($$;$) { html_page($ctx, 200, \$log); } +sub show ($$;$) { + my ($ctx, $oid_b, $fn) = @_; + my $qp = $ctx->{qp}; + my $hints = {}; + while (my ($from, $to) = each %QP_MAP) { + defined(my $v = $qp->{$from}) or next; + $hints->{$to} = $v; + } + + open my $log, '+>', undef or die "open: $!"; + my $solver = PublicInbox::SolverGit->new($ctx->{-inbox}, sub { + solve_result($ctx, $_[0], $log, $hints, $fn); + }); + + # PSGI server will call this and give us a callback + sub { + $ctx->{-wcb} = $_[0]; # HTTP write callback + $solver->solve($ctx->{env}, $log, $oid_b, $hints); + }; +} + 1; -- cgit v1.2.3-24-ge0c7