]> Sergey Matveev's repositories - public-inbox.git/commitdiff
git: *_async: support nested callback invocations
authorEric Wong <e@80x24.org>
Fri, 16 Oct 2020 06:59:33 +0000 (06:59 +0000)
committerEric Wong <e@80x24.org>
Fri, 16 Oct 2020 17:15:24 +0000 (17:15 +0000)
For external indices, we'll need to support nested cat_async
invocations to deduplicate cross-posted messages.

Thus we need to ensure we do not clobber the {inflight*} queues
while stepping through and ensure {cat_rbuf} is stored before
invoking callbacks.

This fixes the ->cat_async-only case, but does not yet
account for the mix of ->check_async interspersed with
->cat_async calls, yet.  More work will be needed on that
front at a later date.

lib/PublicInbox/Git.pm

index 449223eca626e7c37d6de72676803a694061da0f..eb5de159d2e6db16122c43b7c665f62c6d39e754 100644 (file)
@@ -204,14 +204,14 @@ sub cat_async_step ($$) {
        } else {
                $self->fail("Unexpected result from async git cat-file: $head");
        }
-       eval { $cb->($bref, $oid, $type, $size, $arg) };
        $self->{cat_rbuf} = $rbuf if $$rbuf ne '';
+       eval { $cb->($bref, $oid, $type, $size, $arg) };
        warn "E: $oid: $@\n" if $@;
 }
 
 sub cat_async_wait ($) {
        my ($self) = @_;
-       my $inflight = delete $self->{inflight} or return;
+       my $inflight = $self->{inflight} or return;
        while (scalar(@$inflight)) {
                cat_async_step($self, $inflight);
        }
@@ -251,14 +251,14 @@ sub check_async_step ($$) {
                my $ret = my_read($self->{in_c}, $rbuf, $type + 1);
                fail($self, defined($ret) ? 'read EOF' : "read: $!") if !$ret;
        }
+       $self->{chk_rbuf} = $rbuf if $$rbuf ne '';
        eval { $cb->($hex, $type, $size, $arg, $self) };
        warn "E: check($req) $@\n" if $@;
-       $self->{chk_rbuf} = $rbuf if $$rbuf ne '';
 }
 
 sub check_async_wait ($) {
        my ($self) = @_;
-       my $inflight_c = delete $self->{inflight_c} or return;
+       my $inflight_c = $self->{inflight_c} or return;
        while (scalar(@$inflight_c)) {
                check_async_step($self, $inflight_c);
        }
@@ -318,13 +318,15 @@ sub _destroy {
 
 sub cat_async_abort ($) {
        my ($self) = @_;
-       if (my $inflight = delete $self->{inflight}) {
+       if (my $inflight = $self->{inflight}) {
                while (@$inflight) {
                        my ($req, $cb, $arg) = splice(@$inflight, 0, 3);
                        $req =~ s/ .*//; # drop git_dir for Gcf2Client
                        eval { $cb->(undef, $req, undef, undef, $arg) };
                        warn "E: $req: $@ (in abort)\n" if $@;
                }
+               delete $self->{cat_rbuf};
+               delete $self->{inflight};
        }
        cleanup($self);
 }
@@ -357,6 +359,8 @@ sub cleanup {
        delete $self->{async_cat};
        check_async_wait($self);
        cat_async_wait($self);
+       delete $self->{inflight};
+       delete $self->{inflight_c};
        _destroy($self, qw(cat_rbuf in out pid));
        _destroy($self, qw(chk_rbuf in_c out_c pid_c err_c));
        !!($self->{pid} || $self->{pid_c});