diff options
Diffstat (limited to 'lib/PublicInbox/GitAsyncCat.pm')
-rw-r--r-- | lib/PublicInbox/GitAsyncCat.pm | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/lib/PublicInbox/GitAsyncCat.pm b/lib/PublicInbox/GitAsyncCat.pm new file mode 100644 index 00000000..f57e0336 --- /dev/null +++ b/lib/PublicInbox/GitAsyncCat.pm @@ -0,0 +1,53 @@ +# Copyright (C) all contributors <meta@public-inbox.org> +# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt> +package PublicInbox::GitAsyncCat; +use v5.12; +use parent qw(Exporter); +our @EXPORT = qw(ibx_async_cat ibx_async_prefetch async_check); + +our $GCF2C; # singleton PublicInbox::Gcf2Client + +sub ibx_async_cat ($$$$) { + my ($ibx, $oid, $cb, $arg) = @_; + my $isrch = $ibx->{isrch}; + my $git = $isrch ? $isrch->{es}->git : ($ibx->{git} // $ibx->git); + # {topdir} means ExtSearch (likely [extindex "all"]) with potentially + # 100K alternates. git v2.33+ can handle 100k alternates fairly well. + if (!$isrch && !defined($ibx->{topdir}) && !defined($git->{-tmp}) && + ($GCF2C //= eval { + require PublicInbox::Gcf2Client; + PublicInbox::Gcf2Client::new(); + } // 0)) { # 0: do not retry if libgit2 or Inline::C are missing + $GCF2C->gcf2_async("$oid $git->{git_dir}\n", $cb, $arg); + \undef; + } else { # read-only end of git-cat-file pipe + $git->cat_async($oid, $cb, $arg); + $git->watch_async; + } +} + +sub async_check ($$$$) { + my ($ibx, $oidish, $cb, $arg) = @_; # $ibx may be $ctx + my $git = $ibx->{git} // $ibx->git; + $git->check_async($oidish, $cb, $arg); + ($git->{ck} // $git)->watch_async; +} + +# this is safe to call inside $cb, but not guaranteed to enqueue +# returns true if successful, undef if not. For fairness, we only +# prefetch if there's no in-flight requests. +sub ibx_async_prefetch { + my ($ibx, $oid, $cb, $arg) = @_; + my $git = $ibx->git; + if (!defined($ibx->{topdir}) && $GCF2C) { + if (!@{$GCF2C->gcf_inflight // []}) { + $oid .= " $git->{git_dir}\n"; + return $GCF2C->gcf2_async($oid, $cb, $arg); # true + } + } elsif ($git->{epwatch}) { + return $git->async_prefetch($oid, $cb, $arg); + } + undef; +} + +1; |