# Copyright (C) all contributors # License: AGPL-3.0+ 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;