diff options
Diffstat (limited to 'lib/PublicInbox/LeiRemote.pm')
-rw-r--r-- | lib/PublicInbox/LeiRemote.pm | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/lib/PublicInbox/LeiRemote.pm b/lib/PublicInbox/LeiRemote.pm new file mode 100644 index 00000000..399fc936 --- /dev/null +++ b/lib/PublicInbox/LeiRemote.pm @@ -0,0 +1,81 @@ +# Copyright (C) 2021 all contributors <meta@public-inbox.org> +# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt> + +# Make remote externals HTTP(S) inboxes behave like +# PublicInbox::Inbox and PublicInbox::Search/ExtSearch. +# This exists solely for SolverGit. It is a high-latency a +# synchronous API that is not at all fast. +package PublicInbox::LeiRemote; +use v5.10.1; +use strict; +use IO::Uncompress::Gunzip; +use PublicInbox::OnDestroy; +use PublicInbox::MboxReader; +use PublicInbox::Spawn qw(popen_rd); +use PublicInbox::LeiCurl; +use PublicInbox::ContentHash qw(git_sha); + +sub new { + my ($cls, $lei, $uri) = @_; + bless { uri => $uri, lei => $lei }, $cls; +} + +sub isrch { $_[0] } # SolverGit expcets this + +sub _each_mboxrd_eml { # callback for MboxReader->mboxrd + my ($eml, $self) = @_; + my $lei = $self->{lei}; + my $xoids = $lei->{ale}->xoids_for($eml, 1); + if ($lei->{sto} && !$xoids) { # memoize locally + $lei->{sto}->ipc_do('add_eml', $eml); + } + my $smsg = bless {}, 'PublicInbox::Smsg'; + $smsg->{blob} = $xoids ? (keys(%$xoids))[0] + : git_sha(1, $eml)->hexdigest; + $smsg->populate($eml); + $smsg->{mid} //= '(none)'; + push @{$self->{smsg}}, $smsg; +} + +sub mset { + my ($self, $qstr, undef) = @_; # $opt ($_[2]) ignored + my $lei = $self->{lei}; + my $curl = PublicInbox::LeiCurl->new($lei, $lei->{curl}); + push @$curl, '-s', '-d', ''; + my $uri = $self->{uri}->clone; + $uri->query_form(q => $qstr, x => 'm', r => 1); # r=1: relevance + my $cmd = $curl->for_uri($self->{lei}, $uri); + $self->{lei}->qerr("# $cmd"); + my $rdr = { 2 => $lei->{2}, pgid => 0 }; + my ($fh, $pid) = popen_rd($cmd, undef, $rdr); + my $reap = PublicInbox::OnDestroy->new($lei->can('sigint_reap'), $pid); + $self->{smsg} = []; + $fh = IO::Uncompress::Gunzip->new($fh); + PublicInbox::MboxReader->mboxrd($fh, \&_each_mboxrd_eml, $self); + my $err = waitpid($pid, 0) == $pid ? undef + : "BUG: waitpid($cmd): $!"; + @$reap = (); # cancel OnDestroy + my $wait = $self->{lei}->{sto}->ipc_do('done'); + die $err if $err; + $self; # we are the mset (and $ibx, and $self) +} + +sub size { scalar @{$_[0]->{smsg}} } # size of previous results + +sub mset_to_smsg { + my ($self, $ibx, $mset) = @_; # all 3 are $self + wantarray ? ($self->size, @{$self->{smsg}}) : $self->{smsg}; +} + +sub base_url { "$_[0]->{uri}" } + +sub smsg_eml { + my ($self, $smsg) = @_; + if (my $bref = $self->{lei}->ale->git->cat_file($smsg->{blob})) { + return PublicInbox::Eml->new($bref); + } + $self->{lei}->err("E: $self->{uri} $smsg->{blob} gone <$smsg->{mid}>"); + undef; +} + +1; |