about summary refs log tree commit homepage
path: root/lib/PublicInbox/SearchView.pm
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2024-04-24 06:44:47 +0000
committerEric Wong <e@80x24.org>2024-04-24 21:34:47 +0000
commit9987cc1cc687f3b2d03a78938773c4f0c5b64d98 (patch)
tree89a65b32d436ae0b729ed583328aec7836d69b16 /lib/PublicInbox/SearchView.pm
parent1682c7a2264b1083a9cd37151134667edbc31059 (diff)
downloadpublic-inbox-9987cc1cc687f3b2d03a78938773c4f0c5b64d98.tar.gz
The C++ version of xap_helper will allow more complex and
expensive queries.  Both the Perl and C++-only version will
allow offloading search into a separate process which can be
killed via ITIMER_REAL or RLIMIT_CPU in the face of overload.

The xap_helper `mset' command wrapper is simplified to
unconditionally return rank, percentage, and estimated matches
information.  This may slightly penalize mbox retrievals and
lei users, but perhaps that can be a different command entirely.
Diffstat (limited to 'lib/PublicInbox/SearchView.pm')
-rw-r--r--lib/PublicInbox/SearchView.pm56
1 files changed, 32 insertions, 24 deletions
diff --git a/lib/PublicInbox/SearchView.pm b/lib/PublicInbox/SearchView.pm
index 4016ddeb..9919e25c 100644
--- a/lib/PublicInbox/SearchView.pm
+++ b/lib/PublicInbox/SearchView.pm
@@ -30,10 +30,9 @@ sub mbox_results {
 
 sub sres_top_html {
         my ($ctx) = @_;
-        my $srch = $ctx->{ibx}->isrch or
+        my $srch = $ctx->{srch} = $ctx->{ibx}->isrch or
                 return PublicInbox::WWW::need($ctx, 'Search');
         my $q = PublicInbox::SearchQuery->new($ctx->{qp});
-        my $x = $q->{x};
         my $o = $q->{o} // 0;
         my $asc;
         if ($o < 0) {
@@ -41,48 +40,57 @@ sub sres_top_html {
                 $o = -($o + 1); # so [-1] is the last element, like Perl lists
         }
 
-        my $code = 200;
         # double the limit for expanded views:
-        my $opts = {
+        my $opt = {
                 limit => $q->{l},
                 offset => $o,
                 relevance => $q->{r},
                 threads => $q->{t},
                 asc => $asc,
         };
-        my ($mset, $total, $err, $html);
-retry:
-        eval {
-                my $query = $q->{'q'};
-                $srch->query_approxidate($ctx->{ibx}->git, $query);
-                $mset = $srch->mset($query, $opts);
-                $total = $mset->get_matches_estimated;
-        };
-        $err = $@;
+        my $qs = $q->{'q'};
+        $srch->query_approxidate($ctx->{ibx}->git, $qs);
+        sub {
+                $ctx->{wcb} = $_[0]; # PSGI server supplied write cb
+                $srch->async_mset($qs, $opt, \&sres_html_cb, $ctx, $opt, $q);
+        }
+}
+
+sub sres_html_cb { # async_mset cb
+        my ($ctx, $opt, $q, $mset, $err) = @_;
+        my $code = 200;
+        my $total = $mset ? $mset->get_matches_estimated : undef;
         ctx_prepare($q, $ctx);
+        my ($res, $html);
         if ($err) {
                 $code = 400;
                 $html = '<pre>'.err_txt($ctx, $err).'</pre><hr>';
         } elsif ($total == 0) {
-                if (defined($ctx->{-uxs_retried})) {
-                        # undo retry damage:
+                if (defined($ctx->{-uxs_retried})) { # undo retry damage:
                         $q->{'q'} = $ctx->{-uxs_retried};
-                } elsif (index($q->{'q'}, '%') >= 0) {
+                } elsif (index($q->{'q'}, '%') >= 0) { # retry unescaped
                         $ctx->{-uxs_retried} = $q->{'q'};
-                        $q->{'q'} = uri_unescape($q->{'q'});
-                        goto retry;
+                        my $qs = $q->{'q'} = uri_unescape($q->{'q'});
+                        $ctx->{srch}->query_approxidate($ctx->{ibx}->git, $qs);
+                        return $ctx->{srch}->async_mset($qs, $opt,
+                                                \&sres_html_cb, $ctx, $opt, $q);
                 }
                 $code = 404;
                 $html = "<pre>\n[No results found]</pre><hr>";
+        } elsif ($q->{x} eq 'A') {
+                $res = adump($mset, $q, $ctx);
         } else {
-                return adump($mset, $q, $ctx) if $x eq 'A';
-
                 $ctx->{-html_tip} = search_nav_top($mset, $q, $ctx);
-                return mset_thread($ctx, $mset, $q) if $x eq 't';
-                mset_summary($ctx, $mset, $q); # appends to {-html_tip}
-                $html = '';
+                if ($q->{x} eq 't') {
+                        $res = mset_thread($ctx, $mset, $q);
+                } else {
+                        mset_summary($ctx, $mset, $q); # appends to {-html_tip}
+                        $html = '';
+                }
         }
-        html_oneshot($ctx, $code, $html);
+        $res //= html_oneshot($ctx, $code, $html);
+        my $wcb = delete $ctx->{wcb};
+        ref($res) eq 'CODE' ? $res->($wcb) : $wcb->($res);
 }
 
 # display non-nested search results similar to what users expect from